Authentication, take 2; take 3 forthcoming...

*cue sad trombone*
This commit is contained in:
Daniel J. Summers 2016-10-07 22:07:46 -05:00
parent c0237e1433
commit d3a80b9ceb
7 changed files with 63 additions and 49 deletions

View File

@ -8,6 +8,7 @@ open Microsoft.Extensions.Configuration
open Microsoft.Extensions.DependencyInjection open Microsoft.Extensions.DependencyInjection
open Microsoft.Extensions.Logging open Microsoft.Extensions.Logging
open Microsoft.Extensions.Options open Microsoft.Extensions.Options
open RethinkDB.DistributedCache
open System open System
open System.IO 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. // This method gets called by the runtime. Use this method to add services to the container.
member this.ConfigureServices (services : IServiceCollection) = member this.ConfigureServices (services : IServiceCollection) =
ignore <| services.AddOptions () services.AddOptions () |> ignore
ignore <| services.Configure<AppConfig>(this.Configuration.GetSection("MyPrayerJournal")) services.Configure<AppConfig> (this.Configuration.GetSection "MyPrayerJournal") |> ignore
ignore <| services.AddLocalization (fun options -> options.ResourcesPath <- "Resources") services.AddLocalization (fun opt -> opt.ResourcesPath <- "Resources") |> ignore
ignore <| services.AddMvc () services.AddMvc () |> ignore
ignore <| services.AddDistributedMemoryCache () //ignore <| services.AddDistributedMemoryCache ()
// RethinkDB connection // RethinkDB connection
async { async {
let cfg = services.BuildServiceProvider().GetService<IOptions<AppConfig>>().Value let cfg = services.BuildServiceProvider().GetService<IOptions<AppConfig>>().Value
let! conn = DataConfig.Connect cfg.DataConfig let! conn = DataConfig.Connect cfg.DataConfig
do! conn.EstablishEnvironment cfg do! conn.EstablishEnvironment cfg
ignore <| services.AddSingleton conn services.AddSingleton conn |> ignore
//ignore <| services.AddDistributedRethinkDBCache (fun options -> services.AddDistributedRethinkDBCache (fun options ->
// options.Connection <- conn options.Database <- match cfg.DataConfig.Database with null -> "" | db -> db
// options.Database <- match cfg.DataConfig.Database with null -> "" | db -> db options.TableName <- "Session") |> ignore
// options.TableName <- "Session") services.AddSession () |> ignore
ignore <| services.AddSession ()
} |> Async.RunSynchronously } |> Async.RunSynchronously
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // 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) = member this.Configure (app : IApplicationBuilder, env : IHostingEnvironment, loggerFactory : ILoggerFactory) =
ignore <| loggerFactory.AddConsole(this.Configuration.GetSection "Logging") loggerFactory.AddConsole(this.Configuration.GetSection "Logging") |> ignore
ignore <| loggerFactory.AddDebug () loggerFactory.AddDebug () |> ignore
match env.IsDevelopment () with match env.IsDevelopment () with
| true -> ignore <| app.UseDeveloperExceptionPage () | true -> app.UseDeveloperExceptionPage () |> ignore
ignore <| app.UseBrowserLink () app.UseBrowserLink () |> ignore
| _ -> ignore <| app.UseExceptionHandler("/error") | _ -> app.UseExceptionHandler "/error" |> ignore
ignore <| app.UseStaticFiles () app.UseStaticFiles () |> ignore
ignore <| app.UseCookieAuthentication( app.UseCookieAuthentication(
CookieAuthenticationOptions( CookieAuthenticationOptions(
AuthenticationScheme = Keys.Authentication, AuthenticationScheme = Keys.Authentication,
LoginPath = PathString("/user/log-on"), LoginPath = PathString "/user/log-on",
AutomaticAuthenticate = true, AutomaticAuthenticate = true,
AutomaticChallenge = true, AutomaticChallenge = true,
ExpireTimeSpan = TimeSpan(2, 0, 0), ExpireTimeSpan = TimeSpan (2, 0, 0),
SlidingExpiration = true)) SlidingExpiration = true)) |> ignore
ignore <| app.UseMvc(fun routes -> app.UseMvc(fun routes ->
ignore <| routes.MapRoute(name = "default", template = "{controller=Home}/{action=Index}/{id?}")) routes.MapRoute(name = "default", template = "{controller=Home}/{action=Index}/{id?}") |> ignore) |> ignore
/// Default to Development environment /// Default to Development environment
let defaults = seq { yield WebHostDefaults.EnvironmentKey, "Development" } let defaults = seq { yield WebHostDefaults.EnvironmentKey, "Development" }
@ -81,12 +81,12 @@ let main argv =
.AddEnvironmentVariables("ASPNETCORE_") .AddEnvironmentVariables("ASPNETCORE_")
.AddCommandLine(argv) .AddCommandLine(argv)
.Build() .Build()
use host =
WebHostBuilder() WebHostBuilder()
.UseConfiguration(cfg) .UseConfiguration(cfg)
.UseKestrel() .UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory()) .UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>() .UseStartup<Startup>()
.Build() .Build()
.Run() host.Run()
0 0

View File

@ -2,20 +2,23 @@ namespace MyPrayerJournal.Controllers
open Microsoft.AspNetCore.Authorization open Microsoft.AspNetCore.Authorization
open Microsoft.AspNetCore.Mvc open Microsoft.AspNetCore.Mvc
open Microsoft.Extensions.Logging
open MyPrayerJournal open MyPrayerJournal
open RethinkDb.Driver.Net open RethinkDb.Driver.Net
/// Home controller /// Home controller
[<Authorize>] [<Authorize>]
[<Route("")>] [<Route("")>]
type HomeController(data : IConnection) = type HomeController(data : IConnection, logger : ILogger<HomeController>) =
inherit ApplicationController(data) inherit ApplicationController(data)
[<AllowAnonymous>] [<AllowAnonymous>]
[<HttpGet("")>] [<HttpGet("")>]
member this.Index() = member this.Index() =
logger.LogDebug(Newtonsoft.Json.JsonConvert.SerializeObject this.HttpContext.User)
async { async {
match this.HttpContext.User with match this.HttpContext.User with
| :? AppUser as user -> return this.View "Dashboard" :> IActionResult | :? AppUser as user -> return this.View "Dashboard" :> IActionResult
| _ -> return upcast this.View () | _ -> return upcast this.View ()
} |> Async.StartAsTask }
|> Async.StartAsTask

View File

@ -25,7 +25,7 @@ type UserController(data : IConnection, cfg : IOptions<AppConfig>) =
async { async {
let! user = data.LogOnUser form.Email (User.HashPassword form.Password cfg.Value.PasswordSaltBytes) let! user = data.LogOnUser form.Email (User.HashPassword form.Password cfg.Value.PasswordSaltBytes)
match user with 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 // TODO: welcome message
(* this.Session.[Keys.User] <- usr (* this.Session.[Keys.User] <- usr
{ UserMessage.Empty with Level = Level.Info { UserMessage.Empty with Level = Level.Info
@ -37,13 +37,13 @@ type UserController(data : IConnection, cfg : IOptions<AppConfig>) =
|> model.AddMessage |> model.AddMessage
return this.Redirect "/user/log-on" model *) return this.Redirect "/user/log-on" model *)
return upcast this.RedirectToAction "ShowLogOn" return upcast this.RedirectToAction "ShowLogOn"
//return this.View() }
} |> Async.StartAsTask |> Async.StartAsTask
[<HttpGet("log-off")>] [<HttpGet("log-off")>]
member this.LogOff () = member this.LogOff () =
async { async {
do! this.HttpContext.Authentication.SignOutAsync(Keys.Authentication) do! this.HttpContext.Authentication.SignOutAsync Keys.Authentication
// TODO: goodbye message // TODO: goodbye message
return this.LocalRedirect "/" return this.LocalRedirect "/"
} |> Async.StartAsTask } |> Async.StartAsTask

View File

@ -75,7 +75,8 @@ type IConnection with
Email = "test@example.com" Email = "test@example.com"
PasswordHash = User.HashPassword "password" cfg.PasswordSaltBytes PasswordHash = User.HashPassword "password" cfg.PasswordSaltBytes
Name = "Default User" Name = "Default User"
TimeZone = "America/Chicago" }).RunResultAsync(this) TimeZone = "America/Chicago"
}).RunResultAsync(this)
logStepEnd () logStepEnd ()
| _ -> () | _ -> ()
} }

View File

@ -75,6 +75,6 @@
<script src="~/js/site.min.js" asp-append-version="true"></script> <script src="~/js/site.min.js" asp-append-version="true"></script>
</environment> </environment>
@RenderSection("scripts", required: false) @RenderSection("Scripts", required: false)
</body> </body>
</html> </html>

View File

@ -29,3 +29,12 @@
</div> </div>
</div> </div>
</form> </form>
@section Scripts
{
<script type="text/javascript">
/* <![CDATA[ */
$(document).ready(function () { $("#Email").focus() })
/* ]]> */
</script>
}

View File

@ -37,6 +37,7 @@
}, },
"Newtonsoft.Json": "9.0.1", "Newtonsoft.Json": "9.0.1",
"NodaTime": "2.0.0-alpha20160729", "NodaTime": "2.0.0-alpha20160729",
"RethinkDB.DistributedCache": "0.9.0-alpha01",
"RethinkDb.Driver": "2.3.15" "RethinkDb.Driver": "2.3.15"
}, },