Esempio n. 1
0
        public static async Task Run(
            [TimerTrigger("%SessionizeReadModelSyncSchedule%")]
            TimerInfo timer,
            ILogger log,
            [BindConferenceConfig]
            ConferenceConfig conference,
            [BindKeyDatesConfig]
            KeyDatesConfig keyDates,
            [BindSubmissionsConfig]
            SubmissionsConfig submissions,
            [BindSessionizeSyncConfig]
            SessionizeSyncConfig sessionize
            )
        {
            if (keyDates.After(x => x.StopSyncingSessionsFromDate))
            {
                log.LogInformation("SessionizeReadModelSync sync date passed");
                return;
            }

            using (var httpClient = new HttpClient())
            {
                var apiClient = new SessionizeApiClient(httpClient, sessionize.SubmissionsApiKey);
                var(sessionsRepo, presentersRepo) = await submissions.GetRepositoryAsync();

                await SyncService.Sync(apiClient, sessionsRepo, presentersRepo, log, new DateTimeProvider(), conference.ConferenceInstance);
            }
        }
Esempio n. 2
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)]
            HttpRequest req,
            ILogger log,
            [BindConferenceConfig]
            ConferenceConfig conference,
            [BindKeyDatesConfig]
            KeyDatesConfig keyDates,
            [BindSubmissionsConfig]
            SubmissionsConfig submissions
            )
        {
            if (keyDates.Before(x => x.SubmissionsAvailableFromDate) || keyDates.After(x => x.SubmissionsAvailableToDate))
            {
                log.LogWarning("Attempt to access GetSubmissions endpoint outside of allowed window of {start} -> {end}.", keyDates.SubmissionsAvailableFromDate, keyDates.SubmissionsAvailableToDate);
                return(new StatusCodeResult(404));
            }

            var(submissionsRepo, submittersRepo) = await submissions.GetRepositoryAsync();

            var receivedSubmissions = await submissionsRepo.GetAllAsync(conference.ConferenceInstance);

            var submitters = await submittersRepo.GetAllAsync(conference.ConferenceInstance);

            var submissionData = receivedSubmissions.Where(x => x.Session != null)
                                 .Select(x => x.GetSession())
                                 .Select(s => new Submission
            {
                Id         = s.Id.ToString(),
                Title      = s.Title,
                Abstract   = s.Abstract,
                Format     = s.Format,
                Level      = s.Level,
                Tags       = s.Tags,
                Presenters = conference.AnonymousSubmissions
                        ? new Submitter[0]
                        : s.PresenterIds.Select(pId => submitters.Where(p => p.Id == pId).Select(p => p.GetPresenter()).Select(p => new Submitter
                {
                    Id              = p.Id.ToString(),
                    Name            = p.Name,
                    Tagline         = p.Tagline,
                    Bio             = p.Bio,
                    ProfilePhotoUrl = p.ProfilePhotoUrl,
                    TwitterHandle   = p.TwitterHandle,
                    WebsiteUrl      = p.WebsiteUrl
                }).Single()).ToArray()
            })
                                 .OrderBy(x => Random.Next())
                                 .ToArray();

            var settings = new JsonSerializerSettings();

            settings.ContractResolver = new DefaultContractResolver();

            return(new JsonResult(submissionData, settings));
        }
Esempio n. 3
0
        public static async Task Run(
            [TimerTrigger("%NewSessionNotificationSchedule%")]
            TimerInfo timer,
            ILogger log,
            [BindConferenceConfig]
            ConferenceConfig conference,
            [BindNewSessionNotificationConfig]
            NewSessionNotificationConfig newSessionNotification,
            [BindSubmissionsConfig]
            SubmissionsConfig submissions)
        {
            var(submissionsRepo, submittersRepo) = await submissions.GetRepositoryAsync();

            var notifiedSessionsRepo = await newSessionNotification.GetRepositoryAsync();

            var allSubmissions = await submissionsRepo.GetAllAsync(conference.ConferenceInstance);

            var allSubmitters = await submittersRepo.GetAllAsync(conference.ConferenceInstance);

            var notifiedSessions = await notifiedSessionsRepo.GetAllAsync();

            var sessionsToNotify = allSubmissions.Where(s => notifiedSessions.All(n => n.Id != s.Id)).ToArray();

            log.LogInformation("Found {numberOfSessions} sessions, {numberOfSessionsAlreadyNotified} already notified and notifying another {numberOfSessionsBeingNotified}", allSubmissions.Count, notifiedSessions.Count, sessionsToNotify.Length);

            using (var client = new HttpClient())
            {
                foreach (var submission in sessionsToNotify)
                {
                    var presenterIds = submission.GetSession().PresenterIds.Select(x => x.ToString()).ToArray();
                    var presenters   = allSubmitters.Where(submitter => presenterIds.Contains(submitter.Id.ToString()));
                    var postContent  = JsonConvert.SerializeObject(new
                    {
                        Session    = submission.GetSession(),
                        Presenters = presenters.Select(x => x.GetPresenter()).ToArray()
                    }, Formatting.None, new StringEnumConverter());

                    // Post the data
                    log.LogInformation("Posting {submissionId} to {logicAppUrl}", submission.Id, newSessionNotification.LogicAppUrl);
                    var response = await client.PostAsync(newSessionNotification.LogicAppUrl, new StringContent(postContent, Encoding.UTF8, "application/json"));

                    if (!response.IsSuccessStatusCode)
                    {
                        log.LogError("Unsuccessful request to post {documentId}; received {statusCode} and {responseBody}", submission.Id, response.StatusCode, await response.Content.ReadAsStringAsync());
                        response.EnsureSuccessStatusCode();
                    }

                    // Persist the notification record
                    await notifiedSessionsRepo.CreateAsync(new NotifiedSessionEntity(submission.Id));
                }
            }
        }
Esempio n. 4
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]
            HttpRequest req,
            ILogger log,
            [BindConferenceConfig]
            ConferenceConfig conference,
            [BindSubmissionsConfig]
            SubmissionsConfig submissions,
            [BindVotingConfig]
            VotingConfig voting,
            [BindTitoSyncConfig]
            TitoSyncConfig tito,
            [BindAppInsightsSyncConfig]
            AppInsightsSyncConfig appInsights)
        {
            // Get submissions
            var(submissionsRepo, submittersRepo) = await submissions.GetRepositoryAsync();

            var receivedSubmissions = await submissionsRepo.GetAllAsync(conference.ConferenceInstance);

            var presenters = await submittersRepo.GetAllAsync(conference.ConferenceInstance);

            // Get votes
            var votingRepo = await voting.GetRepositoryAsync();

            var votes = await votingRepo.GetAllAsync(conference.ConferenceInstance);

            // Get Tito ids
            var ebRepo = await tito.GetRepositoryAsync();

            var titoTickets = await ebRepo.GetAllAsync(conference.ConferenceInstance);

            var titoIds = titoTickets.Select(o => o.TicketId).ToArray();

            // Get AppInsights sessions
            var aiRepo = await appInsights.GetRepositoryAsync();

            var userSessions = await aiRepo.GetAllAsync(conference.ConferenceInstance);

            // Analyse votes
            var analysedVotes = votes.Select(v => new AnalysedVote(v, votes, titoIds, userSessions)).ToArray();

            // Get summary
            var sessions = receivedSubmissions.Select(x => x.GetSession())
                           .Select(s => new SessionWithVotes
            {
                Id         = s.Id.ToString(),
                Title      = s.Title,
                Abstract   = s.Abstract,
                Format     = s.Format,
                Level      = s.Level,
                Tags       = s.Tags,
                Presenters = GetPresentersFromSession(presenters, s, ps => ps.Select(p =>
                                                                                     new Presenter
                {
                    Id              = p.Id.ToString(),
                    Name            = p.Name,
                    Tagline         = p.Tagline,
                    Bio             = p.Bio,
                    ProfilePhotoUrl = p.ProfilePhotoUrl,
                    TwitterHandle   = p.TwitterHandle,
                    WebsiteUrl      = p.WebsiteUrl
                }).ToArray()),
                CreatedDate          = s.CreatedDate,
                ModifiedDate         = s.ModifiedDate,
                IsUnderrepresented   = GetPresentersFromSession(presenters, s, IsUnderrepresented),
                Pronoun              = CollapsePresenterField(presenters, s, p => p.DataFields["Your pronoun"]),
                JobRole              = CollapsePresenterField(presenters, s, p => p.DataFields["How would you identify your job role"]),
                SpeakingExperience   = CollapsePresenterField(presenters, s, p => p.DataFields["How much speaking experience do you have?"]),
                VoteSummary          = new VoteSummary(analysedVotes.Where(v => v.Vote.GetSessionIds().Contains(s.Id.ToString())).ToArray()),
                FirstPreferenceCount = analysedVotes.Count(v => v.Vote.GetSessionIds()[0] == s.Id.ToString()),
                Top3PreferenceCount  = analysedVotes.Count(v => new [] { v.Vote.GetSessionIds()[0], v.Vote.GetSessionIds()[1], v.Vote.GetSessionIds()[2] }.Contains(s.Id.ToString()))
            })
                           .OrderBy(s => s.Title)
                           .ToArray();

            var tagSummaries = sessions.SelectMany(s => s.Tags).Distinct().OrderBy(t => t)
                               .Select(tag => new TagSummary
            {
                Tag         = tag,
                VoteSummary = new VoteSummary(sessions.Where(s => s.Tags.Contains(tag)).SelectMany(s => analysedVotes.Where(v => v.Vote.SessionIds.Contains(s.Id))).ToArray())
            }).ToArray();

            var response = new GetVotesResponse
            {
                VoteSummary  = new VoteSummary(analysedVotes),
                Sessions     = sessions.OrderByDescending(s => s.VoteSummary.RawTotal).ToArray(),
                TagSummaries = tagSummaries,
                Votes        = analysedVotes,
                UserSessions = userSessions.Select(x => new UserSession {
                    UserId = x.UserId, VoteId = x.VoteId, StartTime = x.StartTime
                }).ToArray()
            };
            var settings = new JsonSerializerSettings {
                ContractResolver = new DefaultContractResolver()
            };

            return(new JsonResult(response, settings));
        }
Esempio n. 5
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)]
            HttpRequestMessage req,
            ILogger log,
            [BindConferenceConfig]
            ConferenceConfig conference,
            [BindKeyDatesConfig]
            KeyDatesConfig keyDates,
            [BindSubmissionsConfig]
            SubmissionsConfig submissions,
            [BindVotingConfig]
            VotingConfig voting,
            [BindTitoSyncConfig]
            TitoSyncConfig tickets
            )
        {
            var vote = await req.Content.ReadAsAsync <VoteRequest>();

            var ip = req.GetIpAddress();

            // Within voting window, allowing for 5 minutes of clock drift
            if (keyDates.Before(x => x.VotingAvailableFromDate) || keyDates.After(x => x.VotingAvailableToDate, TimeSpan.FromMinutes(5)))
            {
                log.LogWarning("Attempt to access SubmitVote endpoint outside of allowed window of {start} -> {end}.", keyDates.VotingAvailableFromDate, keyDates.VotingAvailableToDate);
                return(new StatusCodeResult((int)HttpStatusCode.NotFound));
            }

            // Correct number of votes
            var numVotesSubmitted = vote.SessionIds?.Length ?? 0;

            if (numVotesSubmitted < conference.MinVotes || numVotesSubmitted > conference.MaxVotes)
            {
                log.LogWarning("Attempt to submit to SubmitVotes endpoint with incorrect number of votes ({numVotes} rather than {minVotes} - {maxVotes}).", numVotesSubmitted, conference.MinVotes, conference.MaxVotes);
                return(new StatusCodeResult((int)HttpStatusCode.BadRequest));
            }

            // Correct number of indices
            if (numVotesSubmitted != vote.Indices?.Length)
            {
                log.LogWarning("Attempt to submit to SubmitVotes endpoint without matching indices ({numIndices} vs {numVotes}).", vote.Indices?.Length, numVotesSubmitted);
                return(new StatusCodeResult((int)HttpStatusCode.BadRequest));
            }

            // Valid voting start time, allowing for 5 minutes of clock drift
            if (vote.VotingStartTime > keyDates.Now.AddMinutes(5) || vote.VotingStartTime < keyDates.VotingAvailableFromDate.AddMinutes(-5))
            {
                log.LogWarning("Attempt to submit to SubmitVotes endpoint with invalid start time (got {submittedStartTime} instead of {votingStartTime} - {now}).", vote.VotingStartTime, keyDates.VotingAvailableFromDate, keyDates.Now);
                return(new StatusCodeResult((int)HttpStatusCode.BadRequest));
            }

            if (voting.TicketNumberWhileVotingValue == TicketNumberWhileVoting.Required)
            {
                // Get tickets
                var ticketsRepo = await tickets.GetRepositoryAsync();

                var matchedTicket = await ticketsRepo.GetAsync(conference.ConferenceInstance,
                                                               vote.TicketNumber.ToUpperInvariant());

                // Only if you have a valid ticket
                if (string.IsNullOrEmpty(vote.TicketNumber) || matchedTicket == null)
                {
                    log.LogWarning(
                        "Attempt to submit to SubmitVote endpoint without a valid ticket. Ticket id sent was {ticketNumber}",
                        vote.TicketNumber);
                    return(new StatusCodeResult((int)HttpStatusCode.BadRequest));
                }
            }

            // Get submitted sessions
            var(submissionsRepo, _) = await submissions.GetRepositoryAsync();

            var allSubmissions = await submissionsRepo.GetAllAsync(conference.ConferenceInstance);

            var allSubmissionIds = allSubmissions.Where(s => s.Session != null).Select(s => s.Id.ToString()).ToArray();

            // Valid session ids
            if (vote.SessionIds.Any(id => !allSubmissionIds.Contains(id)) || vote.SessionIds.Distinct().Count() != vote.SessionIds.Count())
            {
                log.LogWarning("Attempt to submit to SubmitVotes endpoint with at least one invalid or duplicate submission id (got {sessionIds}).", JsonConvert.SerializeObject(vote.SessionIds));
                return(new StatusCodeResult((int)HttpStatusCode.BadRequest));
            }

            // Valid indices
            if (vote.Indices.Any(index => index <= 0 || index > allSubmissionIds.Count()) || vote.Indices.Distinct().Count() != vote.Indices.Count())
            {
                log.LogWarning("Attempt to submit to SubmitVotes endpoint with at least one invalid or duplicate index (got {indices} when the number of sessions is {totalNumberOfSessions}).", JsonConvert.SerializeObject(vote.Indices), allSubmissionIds.Count());
                return(new StatusCodeResult((int)HttpStatusCode.BadRequest));
            }

            // No existing vote
            var repo = await voting.GetRepositoryAsync();

            var existing = await repo.GetAsync(conference.ConferenceInstance, vote.Id.ToString());

            if (existing != null)
            {
                log.LogWarning("Attempt to submit to SubmitVotes endpoint with a duplicate vote (got {voteId}).", vote.Id);
                return(new StatusCodeResult((int)HttpStatusCode.Conflict));
            }

            // Save vote
            log.LogInformation("Successfully received vote with Id {voteId}; persisting...", vote.Id);
            var voteToPersist = new Vote(conference.ConferenceInstance, vote.Id, vote.SessionIds, vote.Indices, vote.TicketNumber?.ToUpperInvariant(), ip, vote.VoterSessionId, vote.VotingStartTime, keyDates.Now);            await repo.CreateAsync(voteToPersist);

            return(new StatusCodeResult((int)HttpStatusCode.NoContent));
        }
Esempio n. 6
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)]
            HttpRequest req,
            ILogger log,
            [BindConferenceConfig]
            ConferenceConfig conference,
            [BindKeyDatesConfig]
            KeyDatesConfig keyDates,
            [BindSubmissionsConfig]
            SubmissionsConfig submissions
            )
        {
            if (keyDates.Before(x => x.SubmissionsAvailableFromDate) || keyDates.After(x => x.SubmissionsAvailableToDate))
            {
                log.LogWarning("Attempt to access GetSubmissions endpoint outside of allowed window of {start} -> {end}.", keyDates.SubmissionsAvailableFromDate, keyDates.SubmissionsAvailableToDate);
                return(new StatusCodeResult(404));
            }

            var(submissionsRepo, submittersRepo) = await submissions.GetRepositoryAsync();

            var receivedSubmissions = await submissionsRepo.GetAllAsync(conference.ConferenceInstance);

            var submitters = await submittersRepo.GetAllAsync(conference.ConferenceInstance);

            var submissionData = receivedSubmissions.Where(x => x.Session != null)
                                 .Select(x => x.GetSession())
                                 .Select(s =>
            {
                var otherTagsKeys   = s.DataFields.Keys.Where(k => SessionizeAdapter.TagsTitles.Contains(k)).ToList();
                var otherTagsValues = new List <string>();
                foreach (var key in otherTagsKeys)
                {
                    var found = s.DataFields.TryGetValue(key, out var value);
                    if (found)
                    {
                        otherTagsValues.AddRange(value.Split(',').Select(v => v.Trim()).ToList());
                    }
                }

                var tags = otherTagsValues.Union(s.Tags, StringComparer.InvariantCultureIgnoreCase).ToArray();
                return(new Submission
                {
                    Id = s.Id.ToString(),
                    Title = s.Title,
                    Abstract = s.Abstract,
                    Format = s.Format,
                    Level = s.Level,
                    Tags = tags,
                    Presenters = conference.AnonymousSubmissions
                            ? new Submitter[0]
                            : s.PresenterIds.Select(pId => submitters.Where(p => p.Id == pId)
                                                    .Select(p => p.GetPresenter()).Select(p => new Submitter
                    {
                        Id = p.Id.ToString(),
                        Name = AnonymiseName(p.Name),
                        Tagline = p.Tagline,
                        Bio = p.Bio,
                        ProfilePhotoUrl = p.ProfilePhotoUrl,
                        TwitterHandle = p.TwitterHandle,
                        WebsiteUrl = p.WebsiteUrl
                    }).Single()).ToArray()
                });
            })
                                 .OrderBy(x => Random.Next())
                                 .ToArray();

            var settings = new JsonSerializerSettings();

            settings.ContractResolver = new DefaultContractResolver();

            return(new JsonResult(submissionData, settings));
        }