From d3a80b9ceb59bde7188ec499f476f159c9367407 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Fri, 7 Oct 2016 22:07:46 -0500 Subject: [PATCH] Authentication, take 2; take 3 forthcoming... *cue sad trombone* --- src/MyPrayerJournal/App.fs | 70 +++++++++---------- .../Controllers/HomeController.fs | 7 +- .../Controllers/UserController.fs | 8 +-- src/MyPrayerJournal/Data/Data.fs | 13 ++-- .../Views/Shared/_Layout.cshtml | 2 +- .../Views/User/ShowLogOn.cshtml | 11 ++- src/MyPrayerJournal/project.json | 1 + 7 files changed, 63 insertions(+), 49 deletions(-) diff --git a/src/MyPrayerJournal/App.fs b/src/MyPrayerJournal/App.fs index 3044717..699370c 100644 --- a/src/MyPrayerJournal/App.fs +++ b/src/MyPrayerJournal/App.fs @@ -8,6 +8,7 @@ open Microsoft.Extensions.Configuration open Microsoft.Extensions.DependencyInjection open Microsoft.Extensions.Logging open Microsoft.Extensions.Options +open RethinkDB.DistributedCache open System open System.IO @@ -28,46 +29,45 @@ type Startup(env : IHostingEnvironment) = // This method gets called by the runtime. Use this method to add services to the container. member this.ConfigureServices (services : IServiceCollection) = - ignore <| services.AddOptions () - ignore <| services.Configure(this.Configuration.GetSection("MyPrayerJournal")) - ignore <| services.AddLocalization (fun options -> options.ResourcesPath <- "Resources") - ignore <| services.AddMvc () - ignore <| services.AddDistributedMemoryCache () + services.AddOptions () |> ignore + services.Configure (this.Configuration.GetSection "MyPrayerJournal") |> ignore + services.AddLocalization (fun opt -> opt.ResourcesPath <- "Resources") |> ignore + services.AddMvc () |> ignore + //ignore <| services.AddDistributedMemoryCache () // RethinkDB connection async { let cfg = services.BuildServiceProvider().GetService>().Value let! conn = DataConfig.Connect cfg.DataConfig do! conn.EstablishEnvironment cfg - ignore <| services.AddSingleton conn - //ignore <| services.AddDistributedRethinkDBCache (fun options -> - // options.Connection <- conn - // options.Database <- match cfg.DataConfig.Database with null -> "" | db -> db - // options.TableName <- "Session") - ignore <| services.AddSession () + services.AddSingleton conn |> ignore + services.AddDistributedRethinkDBCache (fun options -> + options.Database <- match cfg.DataConfig.Database with null -> "" | db -> db + options.TableName <- "Session") |> ignore + services.AddSession () |> ignore } |> Async.RunSynchronously // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. member this.Configure (app : IApplicationBuilder, env : IHostingEnvironment, loggerFactory : ILoggerFactory) = - ignore <| loggerFactory.AddConsole(this.Configuration.GetSection "Logging") - ignore <| loggerFactory.AddDebug () + loggerFactory.AddConsole(this.Configuration.GetSection "Logging") |> ignore + loggerFactory.AddDebug () |> ignore match env.IsDevelopment () with - | true -> ignore <| app.UseDeveloperExceptionPage () - ignore <| app.UseBrowserLink () - | _ -> ignore <| app.UseExceptionHandler("/error") + | true -> app.UseDeveloperExceptionPage () |> ignore + app.UseBrowserLink () |> ignore + | _ -> app.UseExceptionHandler "/error" |> ignore - ignore <| app.UseStaticFiles () + app.UseStaticFiles () |> ignore - ignore <| app.UseCookieAuthentication( - CookieAuthenticationOptions( - AuthenticationScheme = Keys.Authentication, - LoginPath = PathString("/user/log-on"), - AutomaticAuthenticate = true, - AutomaticChallenge = true, - ExpireTimeSpan = TimeSpan(2, 0, 0), - SlidingExpiration = true)) - ignore <| app.UseMvc(fun routes -> - ignore <| routes.MapRoute(name = "default", template = "{controller=Home}/{action=Index}/{id?}")) + app.UseCookieAuthentication( + CookieAuthenticationOptions( + AuthenticationScheme = Keys.Authentication, + LoginPath = PathString "/user/log-on", + AutomaticAuthenticate = true, + AutomaticChallenge = true, + ExpireTimeSpan = TimeSpan (2, 0, 0), + SlidingExpiration = true)) |> ignore + app.UseMvc(fun routes -> + routes.MapRoute(name = "default", template = "{controller=Home}/{action=Index}/{id?}") |> ignore) |> ignore /// Default to Development environment let defaults = seq { yield WebHostDefaults.EnvironmentKey, "Development" } @@ -81,12 +81,12 @@ let main argv = .AddEnvironmentVariables("ASPNETCORE_") .AddCommandLine(argv) .Build() - - WebHostBuilder() - .UseConfiguration(cfg) - .UseKestrel() - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseStartup() - .Build() - .Run() + use host = + WebHostBuilder() + .UseConfiguration(cfg) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseStartup() + .Build() + host.Run() 0 \ No newline at end of file diff --git a/src/MyPrayerJournal/Controllers/HomeController.fs b/src/MyPrayerJournal/Controllers/HomeController.fs index 00b62a1..1bb8485 100644 --- a/src/MyPrayerJournal/Controllers/HomeController.fs +++ b/src/MyPrayerJournal/Controllers/HomeController.fs @@ -2,20 +2,23 @@ namespace MyPrayerJournal.Controllers open Microsoft.AspNetCore.Authorization open Microsoft.AspNetCore.Mvc +open Microsoft.Extensions.Logging open MyPrayerJournal open RethinkDb.Driver.Net /// Home controller [] [] -type HomeController(data : IConnection) = +type HomeController(data : IConnection, logger : ILogger) = inherit ApplicationController(data) [] [] member this.Index() = + logger.LogDebug(Newtonsoft.Json.JsonConvert.SerializeObject this.HttpContext.User) async { match this.HttpContext.User with | :? AppUser as user -> return this.View "Dashboard" :> IActionResult | _ -> return upcast this.View () - } |> Async.StartAsTask + } + |> Async.StartAsTask diff --git a/src/MyPrayerJournal/Controllers/UserController.fs b/src/MyPrayerJournal/Controllers/UserController.fs index 7d42384..0f06313 100644 --- a/src/MyPrayerJournal/Controllers/UserController.fs +++ b/src/MyPrayerJournal/Controllers/UserController.fs @@ -25,7 +25,7 @@ type UserController(data : IConnection, cfg : IOptions) = async { let! user = data.LogOnUser form.Email (User.HashPassword form.Password cfg.Value.PasswordSaltBytes) match user with - | Some usr -> do! this.HttpContext.Authentication.SignInAsync(Keys.Authentication, AppUser(user)) + | Some usr -> do! this.HttpContext.Authentication.SignInAsync (Keys.Authentication, AppUser user) // TODO: welcome message (* this.Session.[Keys.User] <- usr { UserMessage.Empty with Level = Level.Info @@ -37,13 +37,13 @@ type UserController(data : IConnection, cfg : IOptions) = |> model.AddMessage return this.Redirect "/user/log-on" model *) return upcast this.RedirectToAction "ShowLogOn" - //return this.View() - } |> Async.StartAsTask + } + |> Async.StartAsTask [] member this.LogOff () = async { - do! this.HttpContext.Authentication.SignOutAsync(Keys.Authentication) + do! this.HttpContext.Authentication.SignOutAsync Keys.Authentication // TODO: goodbye message return this.LocalRedirect "/" } |> Async.StartAsTask \ No newline at end of file diff --git a/src/MyPrayerJournal/Data/Data.fs b/src/MyPrayerJournal/Data/Data.fs index d465407..309668c 100644 --- a/src/MyPrayerJournal/Data/Data.fs +++ b/src/MyPrayerJournal/Data/Data.fs @@ -29,7 +29,7 @@ type IConnection with .Filter(ReqlFunction1(fun usr -> upcast usr.["PasswordHash"].Eq(passwordHash))) .RunResultAsync(this) return user |> List.tryHead - } + } /// Set up the environment for MyPrayerJournal member this.EstablishEnvironment (cfg : AppConfig) = @@ -50,7 +50,7 @@ type IConnection with | _ -> logStepStart " Database not found - creating..." do! r.DbCreate("MyPrayerJournal").RunResultAsync(this) logStepEnd () - } + } /// Ensure all tables exit let checkTables () = async { @@ -63,7 +63,7 @@ type IConnection with logStepStart <| sprintf " %s table not found - creating..." tbl do! db().TableCreate(tbl).RunResultAsync(this) logStepEnd() - }) + }) |> List.iter Async.RunSynchronously // Seed the user table if it is empty let! userCount = db().Table(DataTable.User).Count().RunResultAsync(this) @@ -75,7 +75,8 @@ type IConnection with Email = "test@example.com" PasswordHash = User.HashPassword "password" cfg.PasswordSaltBytes Name = "Default User" - TimeZone = "America/Chicago" }).RunResultAsync(this) + TimeZone = "America/Chicago" + }).RunResultAsync(this) logStepEnd () | _ -> () } @@ -95,11 +96,11 @@ type IConnection with | _ -> logStepStart <| sprintf " %s.Email index not found - creating..." DataTable.User do! db().Table(DataTable.User).IndexCreate("Email").RunResultAsync(this) logStepEnd () - } + } async { logStep "Database checks starting" do! checkDatabase () do! checkTables () do! checkIndexes () logStep "Database checks complete" - } + } diff --git a/src/MyPrayerJournal/Views/Shared/_Layout.cshtml b/src/MyPrayerJournal/Views/Shared/_Layout.cshtml index 395ef09..155f070 100644 --- a/src/MyPrayerJournal/Views/Shared/_Layout.cshtml +++ b/src/MyPrayerJournal/Views/Shared/_Layout.cshtml @@ -75,6 +75,6 @@ - @RenderSection("scripts", required: false) + @RenderSection("Scripts", required: false) diff --git a/src/MyPrayerJournal/Views/User/ShowLogOn.cshtml b/src/MyPrayerJournal/Views/User/ShowLogOn.cshtml index 8ee0554..3ed6f49 100644 --- a/src/MyPrayerJournal/Views/User/ShowLogOn.cshtml +++ b/src/MyPrayerJournal/Views/User/ShowLogOn.cshtml @@ -28,4 +28,13 @@

- \ No newline at end of file + + +@section Scripts +{ + +} \ No newline at end of file diff --git a/src/MyPrayerJournal/project.json b/src/MyPrayerJournal/project.json index e00e953..239c9c9 100644 --- a/src/MyPrayerJournal/project.json +++ b/src/MyPrayerJournal/project.json @@ -37,6 +37,7 @@ }, "Newtonsoft.Json": "9.0.1", "NodaTime": "2.0.0-alpha20160729", + "RethinkDB.DistributedCache": "0.9.0-alpha01", "RethinkDb.Driver": "2.3.15" },