// Helper Methods private List <Interface> GetDeviceInterfaces(FarmForgeDataContext context, AskToRegisterDevice message) { var client = new RestClient(new Uri($"http://{message.IpAddress}")); var request = new RestRequest($"{message.InterfaceEndpoint}", Method.GET); // TODO: Add security // request.AddHeader("Authorization", message.SecurityToken); // TODO: Make the conversion more resilient IRestResponse response = client.Execute(request); if (response.StatusCode == HttpStatusCode.OK) { return(JsonConvert.DeserializeObject <List <Interface> >(response.Content)); } else { var logMessage = $"Error getting Interfaces from {message.DeviceName}:{message.IpAddress}"; var logData = new { Response = response.StatusCode.ToString(), response?.Content, response?.ErrorMessage }; var logDataString = JsonConvert.SerializeObject(logData); context.Logs.Add(new Log { Message = logMessage, Data = logDataString }); context.SaveChanges(); return(new List <Interface>()); } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { var settings = new ApiSettings(); Configuration.GetSection("ApiSettings").Bind(settings); var securitySettings = new SecuritySettings(); Configuration.GetSection("SecuritySettings").Bind(securitySettings); // Allow DI for Settings services.Configure <ApiSettings>(Configuration.GetSection("ApiSettings")); services.Configure <SecuritySettings>(Configuration.GetSection("SecuritySettings")); // Setup CORS if (settings.CORS != null) { services.AddCors(options => { options.AddPolicy( "CorsPolicy", builder => builder.WithOrigins(settings.CORS) .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials() ); }); } // Add versioning services.AddApiVersioning(config => { config.DefaultApiVersion = new ApiVersion(settings.MajorVersion, settings.MinorVersion); config.AssumeDefaultVersionWhenUnspecified = true; config.ReportApiVersions = true; }); // Register swagger services services.AddOpenApiDocument(config => { config.PostProcess = document => { document.Info.Version = $"{settings.MajorVersion}.{settings.MinorVersion}"; document.Info.Title = settings.SwaggerSettings.Title; document.Info.Description = settings.SwaggerSettings.Description; document.Info.TermsOfService = settings.SwaggerSettings.TermsOfService; document.Info.Contact = new NSwag.OpenApiContact { Name = settings.SwaggerSettings.ContactName, Email = settings.SwaggerSettings.ContactEmail, Url = settings.SwaggerSettings.ContactURL }; document.Info.License = new NSwag.OpenApiLicense { Name = settings.SwaggerSettings.LicenseName, Url = settings.SwaggerSettings.LicenseURL }; }; }); // Add the DbContext services.AddDbContext <FarmForgeDataContext>(options => { if (settings.DatabaseType == DatabaseType.SQLITE) { options.UseSqlite(settings.ConnectionStrings["Database"]); } else if (settings.DatabaseType == DatabaseType.SQLSERVER) { options.UseSqlServer(settings.ConnectionStrings["Database"]); } }); // Add Akka.net services.AddSingleton((serviceProvider) => { // Create the actor system var actorSystem = ActorSystem.Create("FarmForge"); // Register the actors var serviceScopeFactory = serviceProvider.GetService <IServiceScopeFactory>(); Actors.Add( actorSystem.ActorOf(Props.Create(() => new DeviceActor(serviceScopeFactory)), "DeviceActor" )); Actors.Add( actorSystem.ActorOf(Props.Create(() => new WebSocketActor(serviceScopeFactory)), "WebSocketActor" )); Actors.Add( actorSystem.ActorOf(Props.Create(() => new AuthenticationActor( serviceScopeFactory, securitySettings )), "AuthenticationActor") ); Actors.Add( actorSystem.ActorOf(Props.Create(() => new CropActor(serviceScopeFactory)), "CropActor" )); Actors.Add( actorSystem.ActorOf(Props.Create(() => new CropTypeActor(serviceScopeFactory)), "CropTypeActor" )); Actors.Add( actorSystem.ActorOf(Props.Create(() => new LocationActor(serviceScopeFactory)), "LocationActor" )); Actors.Add( actorSystem.ActorOf(Props.Create(() => new LogTypeActor(serviceScopeFactory)), "LogTypeActor" )); Actors.Add( actorSystem.ActorOf(Props.Create(() => new StatusActor(serviceScopeFactory)), "StatusActor" )); Actors.Add( actorSystem.ActorOf(Props.Create(() => new CropClassificationActor(serviceScopeFactory)), "CropClassificationActor" )); Actors.Add( actorSystem.ActorOf(Props.Create(() => new CropLogActor(serviceScopeFactory)), "CropLogActor" )); Actors.Add( actorSystem.ActorOf(Props.Create(() => new UnitActor(serviceScopeFactory)), "UnitActor" )); Actors.Add( actorSystem.ActorOf(Props.Create(() => new ProductActor(serviceScopeFactory)), "ProductActor" )); Actors.Add( actorSystem.ActorOf(Props.Create(() => new SupplierActor(serviceScopeFactory)), "SupplierActor" )); return(actorSystem); }); // Access Actors via Dependency Injection services.AddSingleton(_ => Actors); // Access HttpContext within AuthenticationHandlers services.AddHttpContextAccessor(); // Add Authorization policies services.AddSingleton <IAuthorizationHandler, AuthenticatedWebClientHandler>(); services.AddAuthorization(options => { options.AddPolicy("AuthenticatedWebClient", policy => policy.Requirements.Add(new AuthenticatedWebClient())); }); // Add JWT options services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = securitySettings.Issuer, ValidAudience = securitySettings.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securitySettings.SecretKey)) }; }); services.AddControllers(); // use PascalCase instead of camelCase in serialization services.AddMvc(setupAction => { setupAction.EnableEndpointRouting = false; }) .AddJsonOptions(jsonOptions => { jsonOptions.JsonSerializerOptions.PropertyNamingPolicy = null; }) .SetCompatibilityVersion(CompatibilityVersion.Version_3_0); FarmForgeDataContext.SetTriggers(); }