private async Task <bool> AreLinesValidAsync(UpdateLinePreferencesViewModel model, CancellationToken cancellationToken) { if (model.FavoriteLines != null) { ITflService service = _tflServiceFactory.CreateService(); ICollection <LineInfo> lines = await service.GetLinesAsync(cancellationToken); IList <string> validLines = lines.Select((p) => p.Id).ToList(); return(model.FavoriteLines.All((p) => validLines.Contains(p))); } return(true); }
public async Task <IActionResult> UpdateLinePreferences( [Bind(nameof(UpdateLinePreferencesViewModel.ETag), nameof(UpdateLinePreferencesViewModel.FavoriteLines))] UpdateLinePreferencesViewModel model, CancellationToken cancellationToken) { if (model == null || string.IsNullOrWhiteSpace(model.ETag)) { return(BadRequest()); } var user = await GetCurrentUserAsync(); if (user == null) { _logger.LogError("Failed to get user to update line preferences."); return(View("Error")); } bool?updated = null; // Do not bother updating the preferences if they are they same bool hasModelBeenUpdated = model.FavoriteLines == null || !model.FavoriteLines.SequenceEqual(user.FavoriteLines); if (hasModelBeenUpdated) { if (!await AreLinesValidAsync(model, cancellationToken)) { return(BadRequest()); } _logger.LogTrace("Updating line preferences for user Id {UserId}.", user.Id); var existingLines = user.FavoriteLines; var newLines = user.FavoriteLines = (model.FavoriteLines ?? Array.Empty <string>()) .OrderBy((p) => p, StringComparer.Ordinal) .ToArray(); // Override the ETag with the one in the model to ensure write consistency user.ETag = model.ETag; var result = await _userManager.UpdateAsync(user); if (result.Succeeded) { _telemetry.TrackLinePreferencesUpdated(user.Id, existingLines, newLines); _logger.LogInformation("Updated line preferences for user Id {UserId}.", user.Id); } else { _logger.LogWarning( "Failed to update line preferences for user '{UserId}' as it would cause a write conflict. ETag: {ETag}.", user.Id, model.ETag); } updated = result.Succeeded; } return(RedirectToRoute(SiteRoutes.Home, new { UpdateSuccess = updated })); }