public static async Task Run( [TimerTrigger("%SessionizeReadModelSyncSchedule%")] TimerInfo timer, ILogger log, [BindConferenceConfig] ConferenceConfig conference, [BindKeyDatesConfig] KeyDatesConfig keyDates, [BindSessionsConfig] SessionsConfig sessions, [BindSessionizeSyncConfig] SessionizeSyncConfig sessionize ) { if (keyDates.Before(x => x.StopSyncingSessionsFromDate) || keyDates.After(x => x.StopSyncingAgendaFromDate)) { log.LogInformation("SessionizeAgendaSync sync not active"); return; } using (var httpClient = new HttpClient()) { var apiClient = new SessionizeApiClient(httpClient, sessionize.AgendaApiKey); var(sessionsRepo, presentersRepo) = await sessions.GetRepositoryAsync(); await SyncService.Sync(apiClient, sessionsRepo, presentersRepo, log, new DateTimeProvider(), conference.ConferenceInstance); } }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req, ILogger log, [BindConferenceConfig] ConferenceConfig conference, [BindFeedbackConfig] FeedbackConfig feedbackConfig) { var(conferenceFeedbackRepo, sessionFeedbackRepo) = await feedbackConfig.GetRepositoryAsync(); var conferenceFeedback = await conferenceFeedbackRepo.GetAllAsync(conference.ConferenceInstance); var sessionFeedback = await sessionFeedbackRepo.GetAllAsync(conference.ConferenceInstance); var prizeDraw = conferenceFeedback.Select(x => x.Name) .Where(name => sessionFeedback.Count(s => s.Name.ToLowerInvariant() == name.ToLowerInvariant()) >= conference.MinNumSessionFeedbackForPrizeDraw) .ToArray(); var settings = new JsonSerializerSettings(); settings.ContractResolver = new DefaultContractResolver(); return(new JsonResult(prizeDraw, settings)); }
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)); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req, ILogger log, [BindConferenceConfig] ConferenceConfig conference, [BindFeedbackConfig] FeedbackConfig feedbackConfig, [BindSessionsConfig] SessionsConfig sessionsConfig) { var(conferenceFeedbackRepo, sessionFeedbackRepo) = await feedbackConfig.GetRepositoryAsync(); var conferenceFeedback = await conferenceFeedbackRepo.GetAllAsync(conference.ConferenceInstance); var sessionFeedback = await sessionFeedbackRepo.GetAllAsync(conference.ConferenceInstance); var(sessionsRepo, presentersRepo) = await sessionsConfig.GetRepositoryAsync(); var sessions = await sessionsRepo.GetAllAsync(conference.ConferenceInstance); var presenters = await presentersRepo.GetAllAsync(conference.ConferenceInstance); var feedback = new { Conference = conferenceFeedback.OrderBy(x => x.Timestamp).Select(x => new { x.Timestamp, x.Rating, x.Liked, x.ImprovementIdeas }), Sessions = sessions.Select(x => x.GetSession()) .Select(s => new { s.Id, s.Title, Presenters = string.Join(", ", s.PresenterIds.Select(pId => presenters.Single(p => p.Id == pId)).Select(x => x.Name)), Feedback = sessionFeedback.OrderBy(x => x.Timestamp).Where(x => x.SessionName.ToLowerInvariant().Contains(s.Title.ToLowerInvariant())).Select(x => new { x.Timestamp, x.Rating, x.Liked, x.ImprovementIdeas }) }) }; var settings = new JsonSerializerSettings(); settings.ContractResolver = new DefaultContractResolver(); return(new JsonResult(feedback, settings)); }
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)); } } }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req, ILogger log, [BindConferenceConfig] ConferenceConfig conference, [BindKeyDatesConfig] KeyDatesConfig keyDates, [BindSessionsConfig] SessionsConfig sessionsConfig) { if (keyDates.Before(x => x.SubmissionsAvailableToDate)) { log.LogWarning("Attempt to access GetAgenda endpoint before they are available at {availableDate}.", keyDates.SubmissionsAvailableToDate); return(new StatusCodeResult(404)); } var(sessionsRepo, presentersRepo) = await sessionsConfig.GetRepositoryAsync(); var sessions = await sessionsRepo.GetAllAsync(conference.ConferenceInstance); var presenters = await presentersRepo.GetAllAsync(conference.ConferenceInstance); var agenda = sessions.Select(x => x.GetSession()) .Select(s => new Session { Id = s.Id.ToString(), Title = s.Title, Abstract = s.Abstract, Format = s.Format, Level = s.Level, Tags = s.Tags, Presenters = s.PresenterIds.Select(pId => presenters.Where(p => p.Id == pId).Select(p => p.GetPresenter()).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 }).Single()).ToArray() }) .OrderBy(x => x.Title) .ToArray(); var settings = new JsonSerializerSettings(); settings.ContractResolver = new DefaultContractResolver(); return(new JsonResult(agenda, settings)); }
public static async Task Run( [TimerTrigger("%TitoSyncSchedule%")] TimerInfo timer, ILogger log, [BindConferenceConfig] ConferenceConfig conference, [BindKeyDatesConfig] KeyDatesConfig keyDates, [BindTitoSyncConfig] TitoSyncConfig config ) { if (keyDates.After(x => x.StopSyncingTitoFromDate, TimeSpan.FromMinutes(10))) { log.LogInformation("TitoSync sync date passed"); return; } var ids = new List <string>(); var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", $"token={config.ApiKey}"); var(tickets, hasMoreItems, nextPage) = await GetTicketsAsync(httpClient, config, log); if (tickets != null && tickets.Any()) { ids.AddRange(tickets.Select(o => o.Id)); log.LogInformation("Retrieved {ticketsCount} tickets from Tito.", tickets.Count()); } while (hasMoreItems) { (tickets, hasMoreItems, nextPage) = await GetTicketsAsync(httpClient, config, log, nextPage.Value); if (tickets != null && tickets.Any()) { log.LogInformation("Found more {ticketsCount} tickets from Tito.", tickets.Count()); ids.AddRange(tickets.Select(o => o.Id)); } } var repo = await config.GetRepositoryAsync(); var existingTickets = await repo.GetAllAsync(conference.ConferenceInstance); // Taking up to 100 records to meet Azure Storage Bulk Operation limit var newTickets = ids.Except(existingTickets.Select(x => x.TicketId).ToArray()).Distinct().Take(100).ToArray(); log.LogInformation( "Found {existingCount} existing tickets and {currentCount} current tickets. Inserting {newCount} new tickets.", existingTickets.Count, ids.Count, newTickets.Count()); await repo.CreateBatchAsync(newTickets.Select(o => new TitoTicket(conference.ConferenceInstance, o)) .ToArray()); }
public static async Task Run( [TimerTrigger("%TitoSyncSchedule%")] TimerInfo timer, ILogger log, [BindConferenceConfig] ConferenceConfig conference, [BindKeyDatesConfig] KeyDatesConfig keyDates, [BindTitoSyncConfig] TitoSyncConfig titoSyncConfig ) { if (keyDates.After(x => x.StopSyncingTitoFromDate, TimeSpan.FromMinutes(10))) { log.LogInformation("TitoSync sync date passed"); return; } var ids = new List <string>(); var http = new HttpClient(); http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", $"token={titoSyncConfig.ApiKey}"); var(registrations, hasMoreItems, nextPage) = await GetRegistrationsAsync(http, $"https://api.tito.io/v3/{titoSyncConfig.AccountId}/{titoSyncConfig.EventId}/registrations/"); ids.AddRange(registrations.Select(o => o.Id)); while (hasMoreItems) { (registrations, hasMoreItems, nextPage) = await GetRegistrationsAsync(http, $"https://api.tito.io/v3/{titoSyncConfig.AccountId}/{titoSyncConfig.EventId}/registrations?page={nextPage}"); ids.AddRange(registrations.Select(o => o.Id)); } var repo = await titoSyncConfig.GetRepositoryAsync(); var existingOrders = await repo.GetAllAsync(conference.ConferenceInstance); // Taking up to 100 records to meet Azure Storage Bulk Operation limit var newOrders = ids.Except(existingOrders.Select(x => x.OrderId).ToArray()).Distinct().Take(100).ToArray(); log.LogInformation( "Found {existingCount} existing orders and {currentCount} current orders. Inserting {newCount} new orders.", existingOrders.Count, ids.Count, newOrders.Count()); await repo.CreateBatchAsync(newOrders.Select(o => new TitoOrder(conference.ConferenceInstance, o)) .ToArray()); }
public static async Task Run( [TimerTrigger("%AppInsightsSyncSchedule%")] TimerInfo timer, ILogger log, [BindConferenceConfig] ConferenceConfig conference, [BindAppInsightsSyncConfig] AppInsightsSyncConfig appInsights, [BindKeyDatesConfig] KeyDatesConfig keyDates ) { if (keyDates.Before(x => x.StartSyncingAppInsightsFromDate) || keyDates.After(x => x.StopSyncingAppInsightsFromDate, TimeSpan.FromMinutes(10))) { log.LogInformation("AppInsightsSync sync not active"); return; } var http = new HttpClient(); http.DefaultRequestHeaders.Add("x-api-key", appInsights.ApplicationKey); var response = await http.GetAsync($"https://api.applicationinsights.io/v1/apps/{appInsights.ApplicationId}/query?timespan={WebUtility.UrlEncode(keyDates.StartSyncingAppInsightsFrom)}%2F{WebUtility.UrlEncode(keyDates.StopSyncingAppInsightsFrom)}&query={WebUtility.UrlEncode(VotingUserQuery.Query)}"); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsAsync <AppInsightsQueryResponse <VotingUserQuery> >(); var currentRecords = content.Data.Select(x => new AppInsightsVotingUser(conference.ConferenceInstance, x.UserId, x.VoteId, x.StartTime)).ToArray(); var repo = await appInsights.GetRepositoryAsync(); var existingRecords = await repo.GetAllAsync(conference.ConferenceInstance); // Taking up to 100 records to meet Azure Storage Bulk Operation limit var newRecords = currentRecords.Except(existingRecords, new AppInsightsVotingUserComparer()).Take(100).ToArray(); log.LogInformation("Found {existingCount} existing app insights voting users and {currentCount} current app insights voting users. Inserting {newCount} new orders.", existingRecords.Count, currentRecords.Length, newRecords.Length); await repo.CreateBatchAsync(newRecords); }
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)); }
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)); }
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)); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestMessage req, ILogger log, [BindConferenceConfig] ConferenceConfig conference, [BindKeyDatesConfig] KeyDatesConfig keyDates, [BindFeedbackConfig] FeedbackConfig feedbackConfig, [BindSessionsConfig] SessionsConfig sessionsConfig ) { var feedback = await req.Content.ReadAsAsync <FeedbackRequest>(); // Within feedback window if (keyDates.Before(x => x.FeedbackAvailableFromDate) || keyDates.After(x => x.FeedbackAvailableToDate)) { log.LogWarning("Attempt to access SubmitFeedback endpoint outside of allowed window of {start} -> {end}.", keyDates.FeedbackAvailableFromDate, keyDates.FeedbackAvailableToDate); return(new StatusCodeResult((int)HttpStatusCode.NotFound)); } // Valid feedback if (string.IsNullOrWhiteSpace(feedback.Likes) && string.IsNullOrWhiteSpace(feedback.ImprovementIdeas)) { log.LogWarning("Attempt to access SubmitFeedback endpoint with invalid feedback details from {DeviceId}", feedback.DeviceId); return(new StatusCodeResult((int)HttpStatusCode.BadRequest)); } var(conferenceFeedbackRepo, sessionFeedbackRepo) = await feedbackConfig.GetRepositoryAsync(); if (feedback.IsConferenceFeedback) { // Save conference feedback log.LogInformation("Successfully received conference feedback for from DeviceId {DeviceId}; persisting...", feedback.DeviceId); var feedbackToPersist = new ConferenceFeedbackEntity( conference.ConferenceInstance, feedback.Name, feedback.Rating.ToString(), feedback.Likes, feedback.ImprovementIdeas, feedback.DeviceId.ToString()); await conferenceFeedbackRepo.CreateAsync(feedbackToPersist); } else { // valid Session existed var(sessionsRepo, presentersRepo) = await sessionsConfig.GetRepositoryAsync(); var allSessions = await sessionsRepo.GetAllAsync(conference.ConferenceInstance); var allPresenters = await presentersRepo.GetAllAsync(conference.ConferenceInstance); var sessionRow = allSessions.First(s => s != null && feedback.SessionId == s.Id.ToString()); if (sessionRow == null && !feedback.IsConferenceFeedback) { log.LogWarning("Attempt to submit to SubmitFeedback endpoint with invalid SessionId {SessionId} from {DeviceId}", feedback.SessionId, feedback.DeviceId); return(new StatusCodeResult((int)HttpStatusCode.BadRequest)); } var session = sessionRow.GetSession(); var presenterNames = string.Join(", ", session.PresenterIds.Select(pId => allPresenters.Single(p => p.Id == pId)).Select(x => x.Name)); // Save feedback log.LogInformation("Successfully received feedback for {SessionId} from DeviceId {DeviceId}; persisting...", feedback.SessionId, feedback.DeviceId); var feedbackToPersist = new SessionFeedbackEntity( session.Id.ToString(), conference.ConferenceInstance, feedback.Name, feedback.Rating.ToString(), feedback.Likes, feedback.ImprovementIdeas, $"{session.Title} - {presenterNames}", feedback.DeviceId.ToString()); await sessionFeedbackRepo.CreateAsync(feedbackToPersist); } return(new StatusCodeResult((int)HttpStatusCode.NoContent)); }
public SlackController(ConferenceConfig conferenceConfig, SlackService slackService) { conferences = conferenceConfig.Conferences; this.slackService = slackService; }