@@ -3,6 +3,7 @@ namespace Auth
33module Domain =
44 open User
55 open Chessie.ErrorHandling
6+ open Chessie
67
78 type LoginRequest = {
89 Username : Username
@@ -26,6 +27,24 @@ module Domain =
2627
2728 type Login = FindUser -> LoginRequest -> AsyncResult< User, LoginError>
2829
30+ let login ( findUser : FindUser ) ( req : LoginRequest ) = asyncTrial {
31+ let! userToFind =
32+ findUser req.Username |> AR.mapFailure Error
33+ match userToFind with
34+ | None ->
35+ return ! AR.fail UsernameNotFound
36+ | Some user ->
37+ match user.Email with
38+ | NotVerified _ ->
39+ return ! AR.fail EmailNotVerified
40+ | Verified _ ->
41+ let isMatchingPassword =
42+ PasswordHash.VerifyPassword req.Password user.PasswordHash
43+ match isMatchingPassword with
44+ | false -> return ! AR.fail PasswordMisMatch
45+ | _ -> return user
46+ }
47+
2948module Suave =
3049 open Suave
3150 open Suave.Filters
@@ -35,6 +54,7 @@ module Suave =
3554 open Domain
3655 open Chessie.ErrorHandling
3756 open Chessie
57+ open User
3858
3959 type LoginViewModel = {
4060 Username : string
@@ -48,14 +68,49 @@ module Suave =
4868 Error = None
4969 }
5070
51- let handleUserLogin ctx = async {
71+ let onLoginSuccess ( user : User ) =
72+ Successful.OK user.Username.Value
73+
74+ let onLoginFailure viewModel loginError =
75+ match loginError with
76+ | PasswordMisMatch ->
77+ let vm =
78+ { viewModel with Error = Some " password didn't match" }
79+ page " guest/login.liquid" vm
80+ | EmailNotVerified ->
81+ let vm =
82+ { viewModel with Error = Some " email not verified" }
83+ page " guest/login.liquid" vm
84+ | UsernameNotFound ->
85+ let vm =
86+ { viewModel with Error = Some " invalid username" }
87+ page " guest/login.liquid" vm
88+ | Error ex ->
89+ printfn " %A " ex
90+ let vm =
91+ { viewModel with Error = Some " something went wrong" }
92+ page " guest/login.liquid" vm
93+
94+ let handleLoginResult viewModel loginResult =
95+ either onLoginSuccess ( onLoginFailure viewModel) loginResult
96+
97+ let handleLoginAsyncResult viewModel aLoginResult =
98+ aLoginResult
99+ |> Async.ofAsyncResult
100+ |> Async.map ( handleLoginResult viewModel)
101+
102+
103+ let handleUserLogin findUser ctx = async {
52104 match bindEmptyForm ctx.request with
53105 | Choice1Of2 ( vm : LoginViewModel ) ->
54106 let result =
55107 LoginRequest.TryCreate ( vm.Username, vm.Password)
56108 match result with
57109 | Success req ->
58- return ! Successful.OK " TODO" ctx
110+ let aLoginResult = login findUser req
111+ let! webpart =
112+ handleLoginAsyncResult vm aLoginResult
113+ return ! webpart ctx
59114 | Failure err ->
60115 let viewModel = { vm with Error = Some err}
61116 return ! page " guest/login.liquid" viewModel ctx
@@ -67,8 +122,9 @@ module Suave =
67122
68123 let renderLoginPage viewModel =
69124 page " guest/login.liquid" viewModel
70- let webpart () =
125+ let webpart getDataCtx =
126+ let findUser = Persistence.findUser getDataCtx
71127 path " /login" >=> choose [
72128 GET >=> renderLoginPage emptyLoginViewModel
73- POST >=> handleUserLogin
129+ POST >=> handleUserLogin findUser
74130 ]
0 commit comments