summaryrefslogtreecommitdiff
path: root/elm/User/Login.elm
blob: d28faf6b97b60d562d7c091f1e1c3a9a7ea51ff6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
module User.Login exposing (main)

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Json.Encode as JE
import Browser
import Browser.Navigation exposing (load)
import Lib.Api as Api
import Gen.Api as GApi
import Gen.UserEdit as GUE
import Gen.Types exposing (adminEMail)
import Lib.Html exposing (..)


main : Program String Model Msg
main = Browser.element
  { init = \ref -> (init ref, Cmd.none)
  , subscriptions = always Sub.none
  , view = view
  , update = update
  }


type alias Model =
  { ref      : String
  , username : String
  , password : String
  , newpass1 : String
  , newpass2 : String
  , state    : Api.State
  , insecure : Bool
  , noteq    : Bool
  }


init : String -> Model
init ref =
  { ref      = ref
  , username = ""
  , password = ""
  , newpass1 = ""
  , newpass2 = ""
  , state    = Api.Normal
  , insecure = False
  , noteq    = False
  }


encodeLogin : Model -> JE.Value
encodeLogin o = JE.object
  [ ("username", JE.string o.username)
  , ("password", JE.string o.password) ]


encodeChangePass : Model -> JE.Value
encodeChangePass o = JE.object
  [ ("username", JE.string o.username)
  , ("oldpass",  JE.string o.password)
  , ("newpass",  JE.string o.newpass1) ]


type Msg
  = Username String
  | Password String
  | Newpass1 String
  | Newpass2 String
  | Submit
  | Submitted GApi.Response


update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    Username n -> ({ model | username = String.toLower n }, Cmd.none)
    Password n -> ({ model | password = n }, Cmd.none)
    Newpass1 n -> ({ model | newpass1 = n, noteq = False }, Cmd.none)
    Newpass2 n -> ({ model | newpass2 = n, noteq = False }, Cmd.none)

    Submit ->
      if not model.insecure
      then ( { model | state = Api.Loading }
           , Api.post "/u/login.json" (encodeLogin model) Submitted )
      else if model.newpass1 /= model.newpass2
      then ( { model | noteq = True }, Cmd.none )
      else ( { model | state = Api.Loading }
           , Api.post "/u/changepass.json" (encodeChangePass model) Submitted )

    Submitted GApi.Success      -> (model, load model.ref)
    Submitted GApi.InsecurePass -> ({ model | insecure = True, state = if model.insecure then Api.Error GApi.InsecurePass else Api.Normal }, Cmd.none)
    Submitted e                 -> ({ model | state = Api.Error e }, Cmd.none)


view : Model -> Html Msg
view model =
  let
    loginBox =
      div [ class "mainbox" ]
      [ h1 [] [ text "Login" ]
      , table [ class "formtable" ]
        [ formField "username::Username"
          [ inputText "username" model.username Username GUE.valUsername
          , br_ 1
          , a [ href "/u/register" ] [ text "No account yet?" ]
          ]
        , formField "password::Password"
          [ inputPassword "password" model.password Password GUE.valPasswordOld
          , br_ 1
          , a [ href "/u/newpass" ] [ text "Forgot your password?" ]
          ]
        ]
     , if model.state == Api.Normal || model.state == Api.Loading
       then text ""
       else div [ class "notice" ]
            [ h2 [] [ text "Trouble logging in?" ]
            , text "If you have not used this login form since October 2014, your account has likely been disabled. You can "
            , a [ href "/u/newpass" ] [ text "reset your password" ]
            , text " to regain access."
            , br_ 2
            , text "Still having trouble? Send a mail to "
            , a [ href <| "mailto:" ++ adminEMail ] [ text adminEMail ]
            , text ". But keep in mind that I can only help you if the email address associated with your account is correct"
            , text " and you still have access to it. Without that, there is no way to prove that the account is yours."
            ]
      ]

    changeBox =
      div [ class "mainbox" ]
      [ h1 [] [ text "Change your password" ]
      , div [ class "warning" ]
        [ h2 [] [ text "Your current password is not secure" ]
        , text "Your current password is in a public database of leaked passwords. You need to change it before you can continue."
        ]
      , table [ class "formtable" ]
        [ formField "newpass1::New password" [ inputPassword "newpass1" model.newpass1 Newpass1 GUE.valPasswordNew ]
        , formField "newpass2::Repeat"
          [ inputPassword "newpass2" model.newpass2 Newpass2 GUE.valPasswordNew
          , br_ 1
          , if model.noteq then b [ class "standout" ] [ text "Passwords do not match" ] else text ""
          ]
        ]
      ]

  in form_ Submit (model.state == Api.Loading)
      [ if model.insecure then changeBox else loginBox
      , div [ class "mainbox" ]
        [ fieldset [ class "submit" ] [ submitButton "Submit" model.state True ]
        ]
      ]