Skip to content

Commit 9f2f590

Browse files
committed
adds login request validation
1 parent 6fd25aa commit 9f2f590

File tree

4 files changed

+53
-3
lines changed

4 files changed

+53
-3
lines changed

src/FsTweet.Web/Auth.fs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,33 @@
11
namespace Auth
22

3+
module Domain =
4+
open User
5+
open Chessie.ErrorHandling
6+
7+
type LoginRequest = {
8+
Username : Username
9+
Password : Password
10+
}
11+
with static member TryCreate (username, password) =
12+
trial {
13+
let! username = Username.TryCreate username
14+
let! password = Password.TryCreate password
15+
return {
16+
Username = username
17+
Password = password
18+
}
19+
}
20+
21+
322
module Suave =
23+
open Suave
424
open Suave.Filters
525
open Suave.Operators
626
open Suave.DotLiquid
27+
open Suave.Form
28+
open Domain
29+
open Chessie.ErrorHandling
30+
open Chessie
731

832
type LoginViewModel = {
933
Username : string
@@ -17,7 +41,28 @@ module Suave =
1741
Error = None
1842
}
1943

44+
let handleUserLogin ctx = async {
45+
match bindEmptyForm ctx.request with
46+
| Choice1Of2 (vm : LoginViewModel) ->
47+
let result =
48+
LoginRequest.TryCreate (vm.Username, vm.Password)
49+
match result with
50+
| Success req ->
51+
return! Successful.OK "TODO" ctx
52+
| Failure err ->
53+
let viewModel =
54+
{vm with Error = Some err}
55+
return! page "guest/login.liquid" viewModel ctx
56+
| Choice2Of2 err ->
57+
let viewModel =
58+
{emptyLoginViewModel with Error = Some err}
59+
return! page "guest/login.liquid" viewModel ctx
60+
}
61+
2062
let renderLoginPage viewModel =
2163
page "guest/login.liquid" viewModel
2264
let webpart () =
23-
path "/login" >=> renderLoginPage emptyLoginViewModel
65+
path "/login" >=> choose [
66+
GET >=> renderLoginPage emptyLoginViewModel
67+
POST >=> handleUserLogin
68+
]

src/FsTweet.Web/Chessie.fs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ let onFailure f xs =
1515
let either onSuccessF onFailureF =
1616
either (onSuccess onSuccessF) (onFailure onFailureF)
1717

18+
let (|Success|Failure|) result =
19+
match result with
20+
| Ok (x,_) -> Success x
21+
| Bad errs -> Failure (List.head errs)
22+
1823
[<RequireQualifiedAccess>]
1924
module AR =
2025
let mapFailure f aResult =

src/FsTweet.Web/User.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,4 @@ type PasswordHash = private PasswordHash of string with
4949

5050
static member Create (password : Password) =
5151
BCrypt.HashPassword(password.Value)
52-
|> PasswordHash
52+
|> PasswordHash

src/FsTweet.Web/views/user/signup.liquid

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<form class="form-signup" method="POST" action="/signup">
1010
<h2 class="form-signup-heading">Join FsTweet Today!</h2>
1111
{% if model.Error %}
12-
<p class="bg-danger">
12+
<p class="alert alert-danger">
1313
{{ model.Error.Value }}
1414
</p>
1515
{% endif %}

0 commit comments

Comments
 (0)