Remotely/Remotely_Server/Startup.cs
2019-04-05 22:23:59 -07:00

247 lines
9.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Remotely_Server.Data;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Identity.UI.Services;
using System.IO;
using Remotely_Server.Services;
using Microsoft.Extensions.FileProviders;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.AspNetCore.SignalR;
using Remotely_Shared.Models;
using Microsoft.AspNetCore.Http.Connections;
using Remotely_Shared.Services;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Identity.UI;
using Microsoft.AspNetCore.Cors.Infrastructure;
using Swashbuckle.AspNetCore.Swagger;
using Newtonsoft.Json;
namespace Remotely_Server
{
public class Startup
{
public Startup(IConfiguration configuration, IHostingEnvironment env)
{
Configuration = configuration;
IsDev = env.IsDevelopment();
}
public IConfiguration Configuration { get; }
private bool IsDev { get; set; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
var dbProvider = Configuration["ApplicationOptions:DBProvider"].ToLower();
if (dbProvider == "sqlite")
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(
Configuration.GetConnectionString("SQLite")));
}
else if (dbProvider == "sqlserver")
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("SQLServer")));
}
else if (dbProvider == "postgresql")
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseNpgsql(
Configuration.GetConnectionString("PostgreSQL")));
}
services.AddIdentity<RemotelyUser, IdentityRole>(options => options.Stores.MaxLengthForKeys = 128)
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddDefaultTokenProviders();
services.ConfigureApplicationCookie(cookieOptions =>
{
cookieOptions.Cookie.SameSite = SameSiteMode.None;
});
var trustedOrigins = Configuration.GetSection("ApplicationOptions:TrustedCorsOrigins").Get<string[]>();
if (trustedOrigins != null)
{
services.AddCors(options =>
{
options.AddPolicy("TrustedOriginPolicy", builder => builder
.WithOrigins(trustedOrigins)
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
);
});
}
services.AddMvcCore()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
services.AddSignalR(options =>
{
options.EnableDetailedErrors = IsDev;
})
.AddJsonProtocol(options =>
{
options.PayloadSerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
})
.AddMessagePackProtocol();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "Remotely API", Version = "v1" });
});
services.AddLogging();
services.AddScoped<IEmailSender, EmailSender>();
services.AddScoped<EmailSender>();
services.AddScoped<DataService>();
services.AddScoped<RemoteControlSessionRecorder>();
services.AddSingleton<ApplicationConfig>();
services.AddSingleton<RandomGenerator>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ApplicationDbContext context, DataService dataService)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
if (bool.Parse(Configuration["ApplicationOptions:UseHSTS"]))
{
app.UseHsts();
}
if (bool.Parse(Configuration["ApplicationOptions:RedirectToHTTPS"]))
{
app.UseHttpsRedirection();
}
}
ConfigureStaticFiles(app);
app.UseCookiePolicy();
// Uncomment to run .NET Core behind a reverse proxy.
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.All
});
app.UseAuthentication();
app.UseSignalR(routes =>
{
routes.MapHub<BrowserSocketHub>("/BrowserHub", options =>
{
options.ApplicationMaxBufferSize = 500000;
options.TransportMaxBufferSize = 500000;
});
routes.MapHub<DeviceSocketHub>("/DeviceHub", options =>
{
options.ApplicationMaxBufferSize = 500000;
options.TransportMaxBufferSize = 500000;
});
routes.MapHub<RCDeviceSocketHub>("/RCDeviceHub", options =>
{
options.ApplicationMaxBufferSize = 2000000;
options.TransportMaxBufferSize = 2000000;
});
routes.MapHub<RCBrowserSocketHub>("/RCBrowserHub", options =>
{
options.ApplicationMaxBufferSize = 2000000;
options.TransportMaxBufferSize = 2000000;
});
});
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Remotely API V1");
});
app.UseCors("TrustedOriginPolicy");
app.UseMvcWithDefaultRoute();
try
{
context.Database.Migrate();
}
catch (Exception ex)
{
dataService.WriteEvent(ex);
}
dataService.SetAllDevicesNotOnline();
dataService.CleanupEmptyOrganizations();
dataService.CleanupOldRecords();
}
private void ConfigureStaticFiles(IApplicationBuilder app)
{
JsonConvert.DefaultSettings = () =>
{
var settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
return settings;
};
var provider = new FileExtensionContentTypeProvider();
// Add new mappings
provider.Mappings[".ps1"] = "application/octet-stream";
provider.Mappings[".exe"] = "application/octet-stream";
provider.Mappings[".appimage"] = "application/octet-stream";
provider.Mappings[".zip"] = "application/octet-stream";
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Downloads")),
RequestPath = new PathString("/Downloads"),
ContentTypeProvider = provider,
DefaultContentType = "application/octet-stream"
});
// Needed for Let's Encrypt.
if (Directory.Exists(Path.Combine(Directory.GetCurrentDirectory(), ".well-known")))
{
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), @".well-known")),
RequestPath = new PathString("/.well-known"),
ServeUnknownFileTypes = true
});
}
}
}
}