void RestartPendingDownloads() { using (var db = DatabaseManager.Open()) { foreach (var map in DatabaseManager.PendingMapDownloads()) { SIM.LogWeb(SIM.Web.MapDownloadStart, map.Name); Uri uri = new Uri(map.Url); DownloadManager.AddDownloadToQueue( uri, map.LocalPath, progress => { Debug.Log($"Map Download at {progress}%"); NotificationManager.SendNotification("MapDownload", new { map.Id, progress }, map.Owner); }, (success, ex) => { var updatedModel = db.Single <MapModel>(map.Id); bool passesValidation = false; if (success) { passesValidation = Validation.BeValidAssetBundle(map.LocalPath); if (!passesValidation) { updatedModel.Error = "You must specify a valid AssetBundle"; } } updatedModel.Status = passesValidation ? "Valid" : "Invalid"; if (ex != null) { updatedModel.Error = ex.Message; } db.Update(updatedModel); NotificationManager.SendNotification("MapDownloadComplete", updatedModel, map.Owner); SIM.LogWeb(SIM.Web.MapDownloadFinish, map.Name); } ); } var added = new HashSet <Uri>(); var vehicles = new VehicleService(); foreach (var vehicle in DatabaseManager.PendingVehicleDownloads()) { Uri uri = new Uri(vehicle.Url); if (added.Contains(uri)) { continue; } added.Add(uri); SIM.LogWeb(SIM.Web.VehicleDownloadStart, vehicle.Name); DownloadManager.AddDownloadToQueue( uri, vehicle.LocalPath, progress => { Debug.Log($"Vehicle Download at {progress}%"); NotificationManager.SendNotification("VehicleDownload", new { vehicle.Id, progress }, vehicle.Owner); }, (success, ex) => { bool passesValidation = success && Validation.BeValidAssetBundle(vehicle.LocalPath); string status = passesValidation ? "Valid" : "Invalid"; vehicles.SetStatusForPath(status, vehicle.LocalPath); vehicles.GetAllMatchingUrl(vehicle.Url).ForEach(v => { if (!passesValidation) { v.Error = "You must specify a valid AssetBundle"; } if (ex != null) { v.Error = ex.Message; } NotificationManager.SendNotification("VehicleDownloadComplete", v, v.Owner); SIM.LogWeb(SIM.Web.VehicleDownloadFinish, vehicle.Name); }); } ); } } }
public SimulationsModule(ISimulationService service, IUserService userService, IClusterService clusterService, IMapService mapService, IVehicleService vehicleService) : base("simulations") { this.RequiresAuthentication(); Get("/", x => { Debug.Log($"Listing simulations"); try { int page = Request.Query["page"]; // TODO: Items per page should be read from personal user settings. // This value should be independent for each module: maps, vehicles and simulation. // But for now 5 is just an arbitrary value to ensure that we don't try and Page a count of 0 int count = Request.Query["count"] > 0 ? Request.Query["count"] : Config.DefaultPageSize; return(service.List(page, count, this.Context.CurrentUser.Identity.Name).Select(sim => { sim.Status = service.GetActualStatus(sim, false); return SimulationResponse.Create(sim); }).ToArray()); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to list simulations: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Get("/{id:long}", x => { long id = x.id; Debug.Log($"Getting simulation with id {id}"); try { var simulation = service.Get(id, this.Context.CurrentUser.Identity.Name); if (simulation.TimeOfDay.HasValue) { simulation.TimeOfDay = DateTime.SpecifyKind(simulation.TimeOfDay.Value, DateTimeKind.Utc); } simulation.Status = service.GetActualStatus(simulation, false); return(SimulationResponse.Create(simulation)); } catch (IndexOutOfRangeException) { Debug.Log($"Simulation with id {id} does not exist"); return(Response.AsJson(new { error = $"Simulation with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to get simulation with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Post("/", x => { Debug.Log($"Adding new simulation"); try { var req = this.BindAndValidate <SimulationRequest>(); if (!ModelValidationResult.IsValid) { var message = ModelValidationResult.Errors.First().Value.First().ErrorMessage; Debug.Log($"Wrong request: {message}"); return(Response.AsJson(new { error = $"Failed to add simulation: {message}" }, HttpStatusCode.BadRequest)); } var simulation = req.ToModel(this.Context.CurrentUser.Identity.Name); simulation.Status = service.GetActualStatus(simulation, true); if (simulation.Status != "Valid") { throw new Exception($"Simulation is invalid"); } simulation.Status = service.GetActualStatus(simulation, false); long id = service.Add(simulation); Debug.Log($"Simulation added with id {id}"); simulation.Id = id; SIM.LogWeb(SIM.Web.SimulationAddName, simulation.Name); try { SIM.LogWeb(SIM.Web.SimulationAddMapName, mapService.Get(simulation.Map.Value, this.Context.CurrentUser.Identity.Name).Name); if (simulation.Vehicles != null) { foreach (var vehicle in simulation.Vehicles) { var vehicleModel = vehicleService.Get(vehicle.Vehicle, this.Context.CurrentUser.Identity.Name); SIM.LogWeb(SIM.Web.SimulationAddVehicleName, vehicleModel.Name); SIM.LogWeb(SIM.Web.SimulationAddBridgeType, vehicleModel.BridgeType); } } SIM.LogWeb(SIM.Web.SimulationAddAPIOnly, simulation.ApiOnly.ToString()); SIM.LogWeb(SIM.Web.SimulationAddInteractiveMode, simulation.Interactive.ToString()); SIM.LogWeb(SIM.Web.SimulationAddHeadlessMode, simulation.Headless.ToString()); try { SIM.LogWeb(SIM.Web.SimulationAddClusterName, clusterService.Get(simulation.Cluster.Value, this.Context.CurrentUser.Identity.Name).Name); } catch { }; SIM.LogWeb(SIM.Web.SimulationAddUsePredefinedSeed, simulation.Seed.ToString()); SIM.LogWeb(SIM.Web.SimulationAddEnableNPC, simulation.UseTraffic.ToString()); SIM.LogWeb(SIM.Web.SimulationAddRandomPedestrians, simulation.UsePedestrians.ToString()); SIM.LogWeb(SIM.Web.SimulationAddTimeOfDay, simulation.TimeOfDay.ToString()); SIM.LogWeb(SIM.Web.SimulationAddRain, simulation.Rain.ToString()); SIM.LogWeb(SIM.Web.SimulationAddWetness, simulation.Wetness.ToString()); SIM.LogWeb(SIM.Web.SimulationAddFog, simulation.Fog.ToString()); SIM.LogWeb(SIM.Web.SimulationAddCloudiness, simulation.Cloudiness.ToString()); } catch { }; return(SimulationResponse.Create(simulation)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to add simulation: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Put("/{id:long}", x => { long id = x.id; Debug.Log($"Updating simulation with id {id}"); try { var req = this.BindAndValidate <SimulationRequest>(); if (!ModelValidationResult.IsValid) { var message = ModelValidationResult.Errors.First().Value.First().ErrorMessage; Debug.Log($"Wrong request: {message}"); return(Response.AsJson(new { error = $"Failed to update simulation: {message}" }, HttpStatusCode.BadRequest)); } var original = service.Get(id, Context.CurrentUser.Identity.Name); var simulation = req.ToModel(original.Owner); simulation.Id = id; simulation.Status = service.GetActualStatus(simulation, true); if (simulation.Status != "Valid") { throw new Exception($"Simulation is invalid"); } simulation.Status = service.GetActualStatus(simulation, false); int result = service.Update(simulation); SIM.LogWeb(SIM.Web.SimulationEditName, simulation.Name); try { SIM.LogWeb(SIM.Web.SimulationEditMapName, mapService.Get(simulation.Map.Value, this.Context.CurrentUser.Identity.Name).Name); if (simulation.Vehicles != null) { foreach (var vehicle in simulation.Vehicles) { try { var vehicleModel = vehicleService.Get(vehicle.Vehicle, this.Context.CurrentUser.Identity.Name); SIM.LogWeb(SIM.Web.SimulationEditVehicleName, vehicleModel.Name); SIM.LogWeb(SIM.Web.SimulationEditBridgeType, vehicleModel.BridgeType); } catch { } } } SIM.LogWeb(SIM.Web.SimulationEditAPIOnly, simulation.ApiOnly.ToString()); SIM.LogWeb(SIM.Web.SimulationEditInteractiveMode, simulation.Interactive.ToString()); SIM.LogWeb(SIM.Web.SimulationEditHeadlessMode, simulation.Headless.ToString()); try { SIM.LogWeb(SIM.Web.SimulationEditClusterName, clusterService.Get(simulation.Cluster.Value, this.Context.CurrentUser.Identity.Name).Name); } catch { }; SIM.LogWeb(SIM.Web.SimulationEditUsePredefinedSeed, simulation.Seed.ToString()); SIM.LogWeb(SIM.Web.SimulationEditEnableNPC, simulation.UseTraffic.ToString()); SIM.LogWeb(SIM.Web.SimulationEditRandomPedestrians, simulation.UsePedestrians.ToString()); SIM.LogWeb(SIM.Web.SimulationEditTimeOfDay, simulation.TimeOfDay.ToString()); SIM.LogWeb(SIM.Web.SimulationEditRain, simulation.Rain.ToString()); SIM.LogWeb(SIM.Web.SimulationEditWetness, simulation.Wetness.ToString()); SIM.LogWeb(SIM.Web.SimulationEditFog, simulation.Fog.ToString()); SIM.LogWeb(SIM.Web.SimulationEditCloudiness, simulation.Cloudiness.ToString()); } catch { } if (result > 1) { throw new Exception($"More than one simulation has id {id}"); } else if (result < 1) { throw new IndexOutOfRangeException(); } return(SimulationResponse.Create(simulation)); } catch (IndexOutOfRangeException) { Debug.Log($"Simulation with id {id} does not exist"); return(Response.AsJson(new { error = $"Simulation with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to update simulation with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Delete("/{id:long}", x => { long id = x.id; Debug.Log($"Removing simulation with id {id}"); try { int result = service.Delete(id, this.Context.CurrentUser.Identity.Name); SIM.LogWeb(SIM.Web.SimulationDelete); if (result > 1) { throw new Exception($"More than one simulation has id {id}"); } if (result < 1) { throw new IndexOutOfRangeException(); } return(new { }); } catch (IndexOutOfRangeException) { Debug.Log($"Simulation with id {id} does not exist"); return(Response.AsJson(new { error = $"Simulation with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to remove simulation with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Post("/{id:long}/start", x => { long id = x.id; Debug.Log($"Starting simulation with id {id}"); try { var current = service.GetCurrent(this.Context.CurrentUser.Identity.Name); if (current != null) { throw new Exception($"Simulation with id {current.Id} is already running"); } var simulation = service.Get(id, this.Context.CurrentUser.Identity.Name); if (service.GetActualStatus(simulation, false) != "Valid") { simulation.Status = "Invalid"; service.Update(simulation); throw new Exception("Cannot start an invalid simulation"); } service.Start(simulation); SIM.LogWeb(SIM.Web.WebClick, "SimulationStart"); return(new { }); } catch (IndexOutOfRangeException) { Debug.Log($"Simulation with id {id} does not exist"); return(Response.AsJson(new { error = $"Simulation with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to start simulation with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Post("/{id:long}/stop", x => { long id = x.id; Debug.Log($"Stopping simulation with id {id}"); try { var simulation = service.GetCurrent(this.Context.CurrentUser.Identity.Name); if (simulation == null || simulation.Id != id) { throw new Exception($"Simulation with id {id} is not running"); } service.Stop(); SIM.LogWeb(SIM.Web.WebClick, "SimulationStop"); return(new { }); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to stop simulation with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); }
void RestartPendingDownloads() { using (var db = DatabaseManager.Open()) { foreach (var map in DatabaseManager.PendingMapDownloads()) { SIM.LogWeb(SIM.Web.MapDownloadStart, map.Name); Uri uri = new Uri(map.Url); DownloadManager.AddDownloadToQueue( uri, map.LocalPath, progress => { Debug.Log($"Map Download at {progress}%"); NotificationManager.SendNotification("MapDownload", new { map.Id, progress }, map.Owner); }, success => { var updatedModel = db.Single <MapModel>(map.Id); updatedModel.Status = success ? "Valid" : "Invalid"; db.Update(updatedModel); NotificationManager.SendNotification("MapDownloadComplete", updatedModel, map.Owner); SIM.LogWeb(SIM.Web.MapDownloadFinish, map.Name); } ); } var added = new HashSet <Uri>(); var vehicles = new VehicleService(); foreach (var vehicle in DatabaseManager.PendingVehicleDownloads()) { Uri uri = new Uri(vehicle.Url); if (added.Contains(uri)) { continue; } added.Add(uri); SIM.LogWeb(SIM.Web.VehicleDownloadStart, vehicle.Name); DownloadManager.AddDownloadToQueue( uri, vehicle.LocalPath, progress => { Debug.Log($"Vehicle Download at {progress}%"); NotificationManager.SendNotification("VehicleDownload", new { vehicle.Id, progress }, vehicle.Owner); }, success => { string status = success ? "Valid" : "Invalid"; vehicles.SetStatusForPath(status, vehicle.LocalPath); vehicles.GetAllMatchingUrl(vehicle.Url).ForEach(v => { NotificationManager.SendNotification("VehicleDownloadComplete", v, v.Owner); SIM.LogWeb(SIM.Web.VehicleDownloadFinish, vehicle.Name); }); } ); } } }
public VehiclesModule(IVehicleService service, IUserService userService, IDownloadService downloadService, INotificationService notificationService) : base("vehicles") { this.RequiresAuthentication(); Get("/{id}/preview", x => HttpStatusCode.NotFound); Get("/", x => { Debug.Log($"Listing vehicles"); try { int page = Request.Query["page"]; // TODO: Items per page should be read from personal user settings. // This value should be independent for each module: Vehicles, vehicles and simulation. // But for now 5 is just an arbitrary value to ensure that we don't try and Page a count of 0 int count = Request.Query["count"] > 0 ? Request.Query["count"] : Config.DefaultPageSize; return(service.List(page, count, this.Context.CurrentUser.Identity.Name).Select(VehicleResponse.Create).ToArray()); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to list vehicles: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Get("/{id:long}", x => { long id = x.id; Debug.Log($"Getting vehicle with id {id}"); try { var vehicle = service.Get(id, this.Context.CurrentUser.Identity.Name); return(VehicleResponse.Create(vehicle)); } catch (IndexOutOfRangeException) { Debug.Log($"Vehicle with id {id} does not exist"); return(Response.AsJson(new { error = $"Vehicle with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to get vehicle with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Post("/", x => { Debug.Log($"Adding new vehicle"); try { var req = this.BindAndValidate <VehicleRequest>(); if (!ModelValidationResult.IsValid) { var message = ModelValidationResult.Errors.First().Value.First().ErrorMessage; Debug.Log($"Validation for adding vehicle failed: {message}"); return(Response.AsJson(new { error = $"Failed to add vehicle: {message}" }, HttpStatusCode.BadRequest)); } var vehicle = req.ToModel(this.Context.CurrentUser.Identity.Name); var uri = new Uri(vehicle.Url); if (uri.IsFile) { vehicle.Status = "Valid"; vehicle.LocalPath = uri.LocalPath; } else if (service.GetCountOfUrl(vehicle.Url) > 0) { List <VehicleModel> matchingModels = service.GetAllMatchingUrl(vehicle.Url); vehicle.Status = matchingModels[0].Status; vehicle.LocalPath = matchingModels[0].LocalPath; } else { vehicle.Status = "Downloading"; vehicle.LocalPath = WebUtilities.GenerateLocalPath("Vehicles"); } long id = service.Add(vehicle); Debug.Log($"Vehicle added with id {id}"); vehicle.Id = id; SIM.LogWeb(SIM.Web.VehicleAddName, vehicle.Name); SIM.LogWeb(SIM.Web.VehicleAddURL, vehicle.Url); SIM.LogWeb(SIM.Web.VehicleAddBridgeType, vehicle.BridgeType); if (!uri.IsFile && service.GetCountOfUrl(vehicle.Url) == 1) { SIM.LogWeb(SIM.Web.VehicleDownloadStart, vehicle.Name); downloadService.AddDownload( uri, vehicle.LocalPath, progress => notificationService.Send("VehicleDownload", new { vehicle.Id, progress }, vehicle.Owner), success => { string status = success && Validation.BeValidAssetBundle(vehicle.LocalPath) ? "Valid" : "Invalid"; service.SetStatusForPath(status, vehicle.LocalPath); service.GetAllMatchingUrl(vehicle.Url).ForEach(v => { notificationService.Send("VehicleDownloadComplete", v, v.Owner); SIM.LogWeb(SIM.Web.VehicleDownloadFinish, vehicle.Name); }); } ); } return(VehicleResponse.Create(vehicle)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to add vehicle: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Put("/{id:long}", x => { long id = x.id; Debug.Log($"Updating vehicle with id {id}"); try { var req = this.BindAndValidate <VehicleRequest>(); if (!ModelValidationResult.IsValid) { var message = ModelValidationResult.Errors.First().Value.First().ErrorMessage; Debug.Log($"Validation for updating vehicle failed: {message}"); return(Response.AsJson(new { error = $"Failed to update vehicle: {message}" }, HttpStatusCode.BadRequest)); } var vehicle = service.Get(id, this.Context.CurrentUser.Identity.Name); vehicle.Name = req.name; vehicle.Sensors = req.sensors == null ? null : string.Join(",", req.sensors); if (req.sensors != null) { SIM.LogWeb(SIM.Web.VehicleEditSensors); } vehicle.BridgeType = req.bridgeType; SIM.LogWeb(SIM.Web.VehicleEditName, vehicle.Name); SIM.LogWeb(SIM.Web.VehicleEditURL, vehicle.Url); SIM.LogWeb(SIM.Web.VehicleEditBridgeType, vehicle.BridgeType); if (vehicle.Url != req.url) { Uri uri = new Uri(req.url); if (uri.IsFile) { vehicle.Status = "Valid"; vehicle.LocalPath = uri.LocalPath; } else if (service.GetCountOfUrl(req.url) == 0) { vehicle.Status = "Downloading"; vehicle.LocalPath = WebUtilities.GenerateLocalPath("Vehicles"); SIM.LogWeb(SIM.Web.VehicleDownloadStart, vehicle.Name); downloadService.AddDownload( uri, vehicle.LocalPath, progress => notificationService.Send("VehicleDownload", new { vehicle.Id, progress }, vehicle.Owner), success => { string status = success && Validation.BeValidAssetBundle(vehicle.LocalPath) ? "Valid" : "Invalid"; service.SetStatusForPath(status, vehicle.LocalPath); service.GetAllMatchingUrl(vehicle.Url).ForEach(v => { // TODO: We have a bug about flickering vehicles, is it because of that? notificationService.Send("VehicleDownloadComplete", v, v.Owner); SIM.LogWeb(SIM.Web.VehicleDownloadFinish, vehicle.Name); }); } ); } else { List <VehicleModel> vehicles = service.GetAllMatchingUrl(req.url); vehicle.Status = vehicles[0].Status; vehicle.LocalPath = vehicles[0].LocalPath; } vehicle.Url = req.url; } int result = service.Update(vehicle); if (result > 1) { throw new Exception($"More than one vehicle has id {id}"); } else if (result < 1) { throw new IndexOutOfRangeException(); } return(VehicleResponse.Create(vehicle)); } catch (IndexOutOfRangeException) { Debug.Log($"Vehicle with id {id} does not exist"); return(Response.AsJson(new { error = $"Vehicle with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to update vehicle with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Delete("/{id:long}", x => { long id = x.id; Debug.Log($"Removing vehicle with id {id}"); try { VehicleModel vehicle = service.Get(id, this.Context.CurrentUser.Identity.Name); if (service.GetCountOfUrl(vehicle.Url) == 1) { if (vehicle.Status == "Downloading") { downloadService.StopDownload(vehicle.Url); SIM.LogWeb(SIM.Web.VehicleDownloadStop, vehicle.Name); } if (!new Uri(vehicle.Url).IsFile&& File.Exists(vehicle.LocalPath)) { Debug.Log($"Deleting file at path: {vehicle.LocalPath}"); File.Delete(vehicle.LocalPath); } } int result = service.Delete(id, vehicle.Owner); SIM.LogWeb(SIM.Web.VehicleDeleteName, vehicle.Name); SIM.LogWeb(SIM.Web.VehicleDeleteURL, vehicle.Url); SIM.LogWeb(SIM.Web.VehicleDeleteBridgeType, vehicle.BridgeType); if (result > 1) { throw new Exception($"More than one vehicle has id {id}"); } else if (result < 1) { throw new IndexOutOfRangeException(); } return(new { }); } catch (IndexOutOfRangeException) { Debug.Log($"Vehicle with id {id} does not exist"); return(Response.AsJson(new { error = $"Vehicle with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to remove vehicle with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Put("/{id:long}/cancel", x => { long id = x.id; Debug.Log($"Cancelling download of Vehicle with id {id}"); try { VehicleModel vehicle = service.Get(id, this.Context.CurrentUser.Identity.Name); if (vehicle.Status == "Downloading") { downloadService.StopDownload(vehicle.Url); vehicle.Status = "Invalid"; service.Update(vehicle); SIM.LogWeb(SIM.Web.VehicleDownloadStop, vehicle.Name); } else { throw new Exception($"Failed to cancel Vehicle download: Vehicle with id {id} is not currently downloading"); } return(new { }); } catch (IndexOutOfRangeException) { Debug.Log($"Vehicle with id {id} does not exist"); return(Response.AsJson(new { error = $"Vehicle with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to cancel download of vehicle with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Put("/{id:long}/download", x => { long id = x.id; Debug.Log($"Restarting download of Vehicle with id {id}"); try { VehicleModel vehicle = service.Get(id, this.Context.CurrentUser.Identity.Name); Uri uri = new Uri(vehicle.Url); if (!uri.IsFile) { if (vehicle.Status == "Invalid") { vehicle.Status = "Downloading"; downloadService.AddDownload( uri, vehicle.LocalPath, progress => { Debug.Log($"Vehicle Download at {progress}%"); notificationService.Send("VehicleDownload", new { vehicle.Id, progress }, vehicle.Owner); }, success => { var updatedModel = service.Get(id, vehicle.Owner); updatedModel.Status = success && Validation.BeValidAssetBundle(updatedModel.LocalPath) ? "Valid" : "Invalid"; service.Update(updatedModel); notificationService.Send("VehicleDownloadComplete", updatedModel, updatedModel.Owner); SIM.LogWeb(SIM.Web.VehicleDownloadFinish, vehicle.Name); } ); } else { throw new Exception($"Failed to restart download of Vehicle: Vehicle is not in invalid state"); } } else { throw new Exception($"Failed to restart download of Vehicle: file URL is not remote"); } int result = service.Update(vehicle); if (result > 1) { throw new Exception($"More than one Vehicle has id {id}"); } else if (result < 1) { throw new IndexOutOfRangeException(); } return(VehicleResponse.Create(vehicle)); } catch (IndexOutOfRangeException) { Debug.Log($"Vehicle with id {id} does not exist"); return(Response.AsJson(new { error = $"Vehicle with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to cancel download of Vehicle with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); }
public MapsModule(IMapService service, IUserService userService, IDownloadService downloadService, INotificationService notificationService) : base("maps") { this.RequiresAuthentication(); Get("/{id}/preview", x => HttpStatusCode.NotFound); Get("/", x => { Debug.Log($"Listing maps"); try { int page = Request.Query["page"]; // TODO: Items per page should be read from personal user settings. // This value should be independent for each module: maps, vehicles and simulation. // But for now 5 is just an arbitrary value to ensure that we don't try and Page a count of 0 int count = Request.Query["count"] > 0 ? Request.Query["count"] : Config.DefaultPageSize; return(service.List(page, count, this.Context.CurrentUser.Identity.Name).Select(MapResponse.Create).ToArray()); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to list maps: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Get("/{id:long}", x => { long id = x.id; Debug.Log($"Getting map with id {id}"); try { var map = service.Get(id, this.Context.CurrentUser.Identity.Name); return(MapResponse.Create(map)); } catch (IndexOutOfRangeException) { Debug.Log($"Map with id {id} does not exist"); return(Response.AsJson(new { error = $"Map with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to get map with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Post("/", x => { Debug.Log($"Adding new map"); try { var req = this.BindAndValidate <MapRequest>(); if (!ModelValidationResult.IsValid) { var message = ModelValidationResult.Errors.First().Value.First().ErrorMessage; Debug.Log($"Validation for adding map failed: {message}"); return(Response.AsJson(new { error = $"Failed to add map: {message}" }, HttpStatusCode.BadRequest)); } var map = req.ToModel(this.Context.CurrentUser.Identity.Name); var uri = new Uri(map.Url); if (uri.IsFile) { map.Status = "Valid"; map.LocalPath = uri.LocalPath; } else { map.Status = "Downloading"; map.LocalPath = WebUtilities.GenerateLocalPath("Maps"); } long id = service.Add(map); Debug.Log($"Map added with id {id}"); map.Id = id; SIM.LogWeb(SIM.Web.MapAddName, map.Name); SIM.LogWeb(SIM.Web.MapAddURL, map.Url); if (!uri.IsFile) { SIM.LogWeb(SIM.Web.MapDownloadStart, map.Name); downloadService.AddDownload( uri, map.LocalPath, progress => notificationService.Send("MapDownload", new { map.Id, progress }, map.Owner), success => { var updatedModel = service.Get(id, map.Owner); updatedModel.Status = success && Validation.BeValidAssetBundle(updatedModel.LocalPath) ? "Valid" : "Invalid"; service.Update(updatedModel); notificationService.Send("MapDownloadComplete", updatedModel, map.Owner); SIM.LogWeb(SIM.Web.MapDownloadFinish, map.Name); } ); } return(MapResponse.Create(map)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to add map: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Put("/{id:long}", x => { long id = x.id; Debug.Log($"Updating map with id {id}"); try { var req = this.BindAndValidate <MapRequest>(); if (!ModelValidationResult.IsValid) { var message = ModelValidationResult.Errors.First().Value.First().ErrorMessage; Debug.Log($"Validation for updating map failed: {message}"); return(Response.AsJson(new { error = $"Failed to update map: {message}" }, HttpStatusCode.BadRequest)); } var map = service.Get(id, this.Context.CurrentUser.Identity.Name); map.Name = req.name; if (map.Url != req.url) { Uri uri = new Uri(req.url); if (uri.IsFile) { map.Status = "Valid"; map.LocalPath = uri.LocalPath; } else { map.Status = "Downloading"; map.LocalPath = WebUtilities.GenerateLocalPath("Maps"); SIM.LogWeb(SIM.Web.MapDownloadStart, map.Name); downloadService.AddDownload( uri, map.LocalPath, progress => notificationService.Send("MapDownload", new { map.Id, progress }, map.Owner), success => { var updatedModel = service.Get(id, map.Owner); updatedModel.Status = success && Validation.BeValidAssetBundle(updatedModel.LocalPath) ? "Valid" : "Invalid"; service.Update(updatedModel); notificationService.Send("MapDownloadComplete", updatedModel, map.Owner); SIM.LogWeb(SIM.Web.MapDownloadFinish, map.Name); } ); } map.Url = req.url; } int result = service.Update(map); SIM.LogWeb(SIM.Web.MapEditName, map.Name); SIM.LogWeb(SIM.Web.MapEditURL, map.Url); if (result > 1) { throw new Exception($"More than one map has id {id}"); } else if (result < 1) { throw new IndexOutOfRangeException(); } return(MapResponse.Create(map)); } catch (IndexOutOfRangeException) { Debug.Log($"Map with id {id} does not exist"); return(Response.AsJson(new { error = $"Map with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to update map with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Delete("/{id:long}", x => { long id = x.id; Debug.Log($"Removing map with id {id}"); try { MapModel map = service.Get(id, this.Context.CurrentUser.Identity.Name); if (map.Status == "Downloading") { downloadService.StopDownload(map.Url); SIM.LogWeb(SIM.Web.MapDownloadStop, map.Name); } if (!new Uri(map.Url).IsFile&& File.Exists(map.LocalPath)) { Debug.Log($"Deleting file at path: {map.LocalPath}"); File.Delete(map.LocalPath); } int result = service.Delete(id, map.Owner); SIM.LogWeb(SIM.Web.MapDeleteName, map.Name); SIM.LogWeb(SIM.Web.MapDeleteURL, map.Url); if (result > 1) { throw new Exception($"More than one map has id {id}"); } else if (result < 1) { throw new IndexOutOfRangeException(); } return(new { }); } catch (IndexOutOfRangeException) { Debug.Log($"Map with id {id} does not exist"); return(Response.AsJson(new { error = $"Map with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to remove map with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Put("/{id:long}/cancel", x => { long id = x.id; Debug.Log($"Cancelling download of map with id {id}"); try { MapModel map = service.Get(id, this.Context.CurrentUser.Identity.Name); if (map.Status == "Downloading") { downloadService.StopDownload(map.Url); map.Status = "Invalid"; service.Update(map); SIM.LogWeb(SIM.Web.MapDownloadStop, map.Name); } else { throw new Exception($"Failed to cancel map download: map with id {id} is not currently downloading"); } return(new { }); } catch (IndexOutOfRangeException) { Debug.Log($"Map with id {id} does not exist"); return(Response.AsJson(new { error = $"Map with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to cancel download of map with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Put("/{id:long}/download", x => { long id = x.id; Debug.Log($"Restarting download of map with id {id}"); try { MapModel map = service.Get(id, this.Context.CurrentUser.Identity.Name); Uri uri = new Uri(map.Url); if (!uri.IsFile) { if (map.Status == "Invalid") { map.Status = "Downloading"; downloadService.AddDownload( uri, map.LocalPath, progress => { Debug.Log($"Map Download at {progress}%"); notificationService.Send("MapDownload", new { map.Id, progress }, map.Owner); }, success => { var updatedModel = service.Get(id, map.Owner); updatedModel.Status = success && Validation.BeValidAssetBundle(updatedModel.LocalPath) ? "Valid" : "Invalid"; service.Update(updatedModel); notificationService.Send("MapDownloadComplete", updatedModel, map.Owner); SIM.LogWeb(SIM.Web.MapDownloadFinish, map.Name); } ); } else { throw new Exception($"Failed to restart download of map: map is not in invalid state"); } } else { throw new Exception($"Failed to restart download of map: file URL is not remote"); } int result = service.Update(map); if (result > 1) { throw new Exception($"More than one map has id {id}"); } else if (result < 1) { throw new IndexOutOfRangeException(); } return(MapResponse.Create(map)); } catch (IndexOutOfRangeException) { Debug.Log($"Map with id {id} does not exist"); return(Response.AsJson(new { error = $"Map with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to cancel download of map with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); }
public ClustersModule(IClusterService service, IUserService userService) : base("clusters") { this.RequiresAuthentication(); Get("/", x => { Debug.Log($"Listing cluster"); try { string filter = Request.Query["filter"]; int offset = Request.Query["offset"]; // TODO: Items per page should be read from personal user settings. // This value should be independent for each module: maps, vehicles and simulation. // But for now 5 is just an arbitrary value to ensure that we don't try and Page a count of 0 int count = Request.Query["count"] > 0 ? Request.Query["count"] : Config.DefaultPageSize; return(service.List(filter, offset, count, this.Context.CurrentUser.Identity.Name).Select(ClusterResponse.Create).ToArray()); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to list clusters: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Get("/{id:long}", x => { long id = x.id; Debug.Log($"Getting cluster with id {id}"); try { var cluster = service.Get(id, this.Context.CurrentUser.Identity.Name); return(ClusterResponse.Create(cluster)); } catch (IndexOutOfRangeException) { Debug.Log($"Cluster with id {id} does not exist"); return(Response.AsJson(new { error = $"Cluster with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to get cluster with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Post("/", x => { Debug.Log($"Adding new cluster"); try { var req = this.BindAndValidate <ClusterRequest>(); if (!ModelValidationResult.IsValid) { var message = ModelValidationResult.Errors.First().Value.First().ErrorMessage; Debug.Log($"Validation for adding cluster failed: {message}"); return(Response.AsJson(new { error = $"Failed to add cluster: {message}" }, HttpStatusCode.BadRequest)); } var cluster = req.ToModel(this.Context.CurrentUser.Identity.Name); cluster.Status = "Valid"; long id = service.Add(cluster); Debug.Log($"Cluster added with id {id}"); cluster.Id = id; SIM.LogWeb(SIM.Web.ClusterAddName, cluster.Name); SIM.LogWeb(SIM.Web.ClusterAddIPS, cluster.Ips); return(ClusterResponse.Create(cluster)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to add cluster: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Put("/{id:long}", x => { long id = x.id; Debug.Log($"Updating cluster with id {id}"); try { if (id == 0) { throw new Exception("Cannot edit default cluster"); } var req = this.BindAndValidate <ClusterRequest>(); if (!ModelValidationResult.IsValid) { var message = ModelValidationResult.Errors.First().Value.First().ErrorMessage; Debug.Log($"Validation for updating cluster failed: {message}"); return(Response.AsJson(new { error = $"Failed to update cluster: {message}" }, HttpStatusCode.BadRequest)); } var cluster = service.Get(id, this.Context.CurrentUser.Identity.Name); cluster.Name = req.name; cluster.Ips = string.Join(",", req.ips); int result = service.Update(cluster); SIM.LogWeb(SIM.Web.ClusterEditName, cluster.Name); SIM.LogWeb(SIM.Web.ClusterEditIPS, cluster.Ips); if (result > 1) { throw new Exception($"More than one cluster has id {id}"); } else if (result < 1) { throw new IndexOutOfRangeException(); } cluster.Status = "Valid"; return(ClusterResponse.Create(cluster)); } catch (IndexOutOfRangeException) { Debug.Log($"Cluster with id {id} does not exist"); return(Response.AsJson(new { error = $"Cluster with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to update cluster with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); Delete("/{id:long}", x => { long id = x.id; Debug.Log($"Removing cluster with id {id}"); try { if (id == 0) { throw new Exception("Cannot remove default cluster"); } try { var clusterModel = service.Get(id, this.Context.CurrentUser.Identity.Name); SIM.LogWeb(SIM.Web.ClusterDeleteName, clusterModel.Name); SIM.LogWeb(SIM.Web.ClusterDeleteIPS, clusterModel.Ips); } catch { }; int result = service.Delete(id, this.Context.CurrentUser.Identity.Name); if (result > 1) { throw new Exception($"More than one cluster has id {id}"); } if (result < 1) { throw new IndexOutOfRangeException(); } return(new { }); } catch (IndexOutOfRangeException) { Debug.Log($"Cluster with id {id} does not exist"); return(Response.AsJson(new { error = $"Cluster with id {id} does not exist" }, HttpStatusCode.NotFound)); } catch (Exception ex) { Debug.LogException(ex); return(Response.AsJson(new { error = $"Failed to remove cluster with id {id}: {ex.Message}" }, HttpStatusCode.InternalServerError)); } }); }