diff --git a/ServerCore/Areas/Deployment/DeploymentConfiguration.cs b/ServerCore/Areas/Deployment/DeploymentConfiguration.cs new file mode 100644 index 00000000..2a51dc5a --- /dev/null +++ b/ServerCore/Areas/Deployment/DeploymentConfiguration.cs @@ -0,0 +1,35 @@ +using System; +using Microsoft.AspNetCore.Hosting; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using ServerCore.DataModel; + +namespace ServerCore.Areas.Deployment +{ + public class DeploymentConfiguration + { + internal static void ConfigureDatabase(IConfiguration configuration, IServiceCollection services, IHostingEnvironment env) + { + // Use SQL Database if in Azure, otherwise, use localdb + if (env.IsStaging() && Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME") == "PuzzleServerTestDeploy") + { + services.AddDbContext + (options => options.UseLazyLoadingProxies() + .UseSqlServer(configuration.GetConnectionString("PuzzleServerSQLConnectionString"))); + } + else if (env.IsProduction() && (Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME") == "puzzlehunt" || Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME") == "puzzleday")) + { + services.AddDbContext + (options => options.UseLazyLoadingProxies() + .UseSqlServer(configuration.GetConnectionString("PuzzleServerSQLConnectionString"))); + } + else + { + services.AddDbContext + (options => options.UseLazyLoadingProxies() + .UseSqlServer(configuration.GetConnectionString("PuzzleServerContextLocal"))); + } + } + } +} diff --git a/ServerCore/Areas/Identity/IdentityHostingStartup.cs b/ServerCore/Areas/Identity/IdentityHostingStartup.cs index 4a3f9656..4a8ad77c 100644 --- a/ServerCore/Areas/Identity/IdentityHostingStartup.cs +++ b/ServerCore/Areas/Identity/IdentityHostingStartup.cs @@ -1,8 +1,8 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Identity; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using ServerCore.Areas.Deployment; using ServerCore.DataModel; [assembly: HostingStartup(typeof(ServerCore.Areas.Identity.IdentityHostingStartup))] @@ -14,10 +14,16 @@ public void Configure(IWebHostBuilder builder) { builder.ConfigureServices((context, services) => { - services.AddDbContext(options => - options.UseLazyLoadingProxies() - .UseSqlServer( - context.Configuration.GetConnectionString("PuzzleServerContext"))); + // Set up to use Azure settings + IHostingEnvironment env = context.HostingEnvironment; + IConfigurationBuilder configBuilder = new ConfigurationBuilder() + .SetBasePath(env.ContentRootPath) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) + .AddEnvironmentVariables(); + context.Configuration = configBuilder.Build(); + + DeploymentConfiguration.ConfigureDatabase(context.Configuration, services, env); services.AddDefaultIdentity() .AddEntityFrameworkStores(); diff --git a/ServerCore/FileManager.cs b/ServerCore/FileManager.cs index 7727a484..95389f8a 100644 --- a/ServerCore/FileManager.cs +++ b/ServerCore/FileManager.cs @@ -1,14 +1,16 @@ -using Microsoft.WindowsAzure.Storage; -using Microsoft.WindowsAzure.Storage.Blob; -using System; +using System; using System.IO; using System.Security.Cryptography; using System.Threading.Tasks; +using Microsoft.WindowsAzure.Storage; +using Microsoft.WindowsAzure.Storage.Blob; namespace ServerCore { public class FileManager { + public static string ConnectionString { get; set; } + /// /// Uploads a file to blob storage /// @@ -57,9 +59,8 @@ private static async Task GetOrCreateEventContainerAsync(int private static CloudStorageAccount StorageAccount { get - { - // todo: read the account info from configuration - return CloudStorageAccount.Parse("UseDevelopmentStorage=true"); + { + return CloudStorageAccount.Parse(ConnectionString); } } } diff --git a/ServerCore/Program.cs b/ServerCore/Program.cs index d79bc02f..02fed134 100644 --- a/ServerCore/Program.cs +++ b/ServerCore/Program.cs @@ -1,5 +1,8 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; +using Microsoft.Azure.Services.AppAuthentication; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration.AzureKeyVault; namespace ServerCore { @@ -11,8 +14,8 @@ public static void Main(string[] args) } public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); + WebHost.CreateDefaultBuilder(args) + .UseStartup() + .Build(); } } diff --git a/ServerCore/Properties/PublishProfiles/PuzzleServerTestDeploy - Web Deploy.pubxml b/ServerCore/Properties/PublishProfiles/PuzzleServerTestDeploy - Web Deploy.pubxml new file mode 100644 index 00000000..d510126d --- /dev/null +++ b/ServerCore/Properties/PublishProfiles/PuzzleServerTestDeploy - Web Deploy.pubxml @@ -0,0 +1,32 @@ + + + + + MSDeploy + /subscriptions/3ffc52f4-eed1-4312-8170-9caf82ff0949/resourcegroups/PuzzleServerTestDeploy/providers/Microsoft.Web/sites/PuzzleServerTestDeploy + PuzzleServerTestDeploy + AzureWebSite + Release + Any CPU + https://puzzleservertestdeploy.azurewebsites.net + True + False + 67b91cce-4e3d-4f0f-8a76-eafd37c5f949 + puzzleservertestdeploy.scm.azurewebsites.net:443 + PuzzleServerTestDeploy + + True + WMSVC + True + $PuzzleServerTestDeploy + <_SavePWD>True + <_DestinationType>AzureWebSite + False + netcoreapp2.1 + false + <_IsPortable>true + + \ No newline at end of file diff --git a/ServerCore/Properties/launchSettings.json b/ServerCore/Properties/launchSettings.json index d69857f0..58ff0369 100644 --- a/ServerCore/Properties/launchSettings.json +++ b/ServerCore/Properties/launchSettings.json @@ -1,4 +1,4 @@ -{ +{ "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, @@ -8,13 +8,13 @@ } }, "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + },\ "ServerCore": { "commandName": "Project", "launchBrowser": true, @@ -24,4 +24,4 @@ "applicationUrl": "http://localhost:44319/" } } -} +} \ No newline at end of file diff --git a/ServerCore/ServerCore.csproj b/ServerCore/ServerCore.csproj index 6d9ed873..6e922be1 100644 --- a/ServerCore/ServerCore.csproj +++ b/ServerCore/ServerCore.csproj @@ -24,6 +24,7 @@ + diff --git a/ServerCore/Startup.cs b/ServerCore/Startup.cs index 6e02bd26..09a99c49 100644 --- a/ServerCore/Startup.cs +++ b/ServerCore/Startup.cs @@ -1,11 +1,12 @@ -using Microsoft.AspNetCore.Authorization; +using System; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Authorization; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using ServerCore.Areas.Deployment; using ServerCore.Areas.Identity.UserAuthorizationPolicy; using ServerCore.DataModel; @@ -13,9 +14,25 @@ namespace ServerCore { public class Startup { - public Startup(IConfiguration configuration) + private IHostingEnvironment hostingEnvironment; + + public Startup(IConfiguration configuration, IHostingEnvironment env) { Configuration = configuration; + hostingEnvironment = env; + } + + public Startup(IHostingEnvironment env) + { + // Set up to use Azure settings + IConfigurationBuilder configBuilder = new ConfigurationBuilder() + .SetBasePath(env.ContentRootPath) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) + .AddEnvironmentVariables(); + Configuration = configBuilder.Build(); + + hostingEnvironment = env; } public IConfiguration Configuration { get; } @@ -39,9 +56,8 @@ public void ConfigureServices(IServiceCollection services) options.Conventions.AuthorizeFolder("/ModelBases"); }); - services.AddDbContext - (options => options.UseLazyLoadingProxies() - .UseSqlServer(Configuration.GetConnectionString("PuzzleServerContext"))); + DeploymentConfiguration.ConfigureDatabase(Configuration, services, hostingEnvironment); + FileManager.ConnectionString = Configuration.GetConnectionString("AzureStorageConnectionString"); services.AddAuthentication().AddMicrosoftAccount(microsoftOptions => { @@ -87,12 +103,23 @@ public void ConfigureServices(IServiceCollection services) // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { - if (env.IsDevelopment()) + if (env.IsDevelopment() && String.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME"))) { app.UseBrowserLink(); app.UseDeveloperExceptionPage(); PuzzleServerContext.UpdateDatabase(app); } + else if (env.IsStaging() && Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME") == "PuzzleServerTestDeploy") + { + app.UseExceptionHandler("/Error"); + app.UseHsts(); + PuzzleServerContext.UpdateDatabase(app); + } + else if (env.IsProduction() && (Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME") == "puzzlehunt" || Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME") == "puzzleday")) + { + app.UseExceptionHandler("/Error"); + app.UseHsts(); + } else { app.UseExceptionHandler("/Error"); diff --git a/ServerCore/appsettings.Development.json b/ServerCore/appsettings.Development.json index fa8ce71a..7fb9ec8d 100644 --- a/ServerCore/appsettings.Development.json +++ b/ServerCore/appsettings.Development.json @@ -1,4 +1,12 @@ { + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:44319/", + "sslPort": 0 + } + }, "Logging": { "IncludeScopes": false, "LogLevel": { @@ -6,5 +14,9 @@ "System": "Information", "Microsoft": "Information" } + }, + "ConnectionStrings": { + "PuzzleServerContextLocal": "Server=(localdb)\\MSSQLLocalDB;Database=PuzzleServer;Trusted_Connection=True;MultipleActiveResultSets=true", + "AzureStorageConnectionString": "UseDevelopmentStorage=true" } } diff --git a/ServerCore/appsettings.Production.json b/ServerCore/appsettings.Production.json new file mode 100644 index 00000000..567c3a25 --- /dev/null +++ b/ServerCore/appsettings.Production.json @@ -0,0 +1,15 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://puzzlehunt.azurewebsites.net", + "sslPort": 0 + } + }, + "ConnectionStrings": { + "PuzzleServerContext": "", + "AzureStorageConnectionString": "", + "PuzzleServerSQLConnectionString": "" + } +} diff --git a/ServerCore/appsettings.Staging.json b/ServerCore/appsettings.Staging.json new file mode 100644 index 00000000..b016d996 --- /dev/null +++ b/ServerCore/appsettings.Staging.json @@ -0,0 +1,15 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://puzzleservertestdeploy.azurewebsites.net", + "sslPort": 0 + } + }, + "ConnectionStrings": { + "PuzzleServerContext": "", + "AzureStorageConnectionString": "", + "PuzzleServerSQLConnectionString": "" + } +} \ No newline at end of file diff --git a/ServerCore/appsettings.json b/ServerCore/appsettings.json index fafd145a..f484e8a8 100644 --- a/ServerCore/appsettings.json +++ b/ServerCore/appsettings.json @@ -4,9 +4,5 @@ "LogLevel": { "Default": "Warning" } - }, - "ConnectionStrings": { - "PuzzleServerContext": "Server=(localdb)\\MSSQLLocalDB;Database=PuzzleServer;Trusted_Connection=True;MultipleActiveResultSets=true", - "AzureStorageConnectionString-1": "UseDevelopmentStorage=true" } } \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d09985de..f660421b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -18,5 +18,4 @@ steps: publishWebProjects: True arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)' zipAfterPublish: True - - task: PublishBuildArtifacts@1