-- | `App.Page.MailValidation` is a simple interface for mail verification. -- | A token is sent at registration at the provided email address. -- | This token has to be used to validate the email address. module App.Page.MailValidation where import Prelude (Unit, bind, discard, ($), (<<<), (<>), map, show) import Data.Array as A import Data.ArrayBuffer.Types (ArrayBuffer) import Data.Maybe (maybe) import Data.Either (Either(..)) import Effect.Aff.Class (class MonadAff) import Halogen as H import Halogen.HTML as HH import Halogen.HTML.Events as HE import Web.Event.Event as Event import Web.Event.Event (Event) import Bulma as Bulma import App.Type.LogMessage import App.Message.AuthenticationDaemon as AuthD import App.Validation.Login as L import App.Validation.Token as T data Output = MessageToSend ArrayBuffer | Log LogMessage -- | The component is informed when the connection went up or down. data Query a = DoNothing a type Slot = H.Slot Query Output type Input = Unit data RegisterInput = VALIDATION_INP_login String | VALIDATION_INP_token String data Action -- | Simply get the inputs from the form. = HandleValidationInput RegisterInput -- | Validate inputs (login, email, password) then send the request -- | (via `SendMailValidationToken`) or log errors. | ValidateInputs Event -- | Send the registration request to `dnsmanagerd`. -- | This action is automatically called from `ValidateInputs`. | SendMailValidationToken -- | The possible errors come from either the login or token input. data Error = Login (Array L.Error) | Token (Array T.Error) -- | The whole mail validation form is composed of two strings: the login and the token. type MailValidationForm = { login :: String, token :: String } -- | State is composed of the registration form, the errors and an indication whether -- | the websocket connection with `authd` is up or not. type State = { mailValidationForm :: MailValidationForm , errors :: Array Error } component :: forall m. MonadAff m => H.Component Query Input Output m component = H.mkComponent { initialState , render , eval: H.mkEval $ H.defaultEval { handleAction = handleAction } } initialState :: Input -> State initialState _ = { mailValidationForm: { login: "", token: "" } , errors: [] } render :: forall m. State -> H.ComponentHTML Action () m render { mailValidationForm } = Bulma.section_small [ Bulma.columns_ [ b mail_validation_form ] ] where b e = Bulma.column_ [ Bulma.box e ] mail_validation_form = [ Bulma.h3 "Verify your account" , Bulma.div_content [] [Bulma.explanation [Bulma.p "Email addresses must be validated within 30 minutes."]] , render_register_form ] render_register_form = HH.form [ HE.onSubmit ValidateInputs ] [ Bulma.username_input "Username" mailValidationForm.login (HandleValidationInput <<< VALIDATION_INP_login) , Bulma.token_input "Token" mailValidationForm.token (HandleValidationInput <<< VALIDATION_INP_token) , Bulma.btn_validation ] handleAction :: forall m. MonadAff m => Action -> H.HalogenM State Action () Output m Unit handleAction = case _ of HandleValidationInput reginp -> do case reginp of VALIDATION_INP_login v -> H.modify_ _ { mailValidationForm { login = v } } VALIDATION_INP_token v -> H.modify_ _ { mailValidationForm { token = v } } -- Validate inputs (login, token) then send the request -- (via SendMailValidationToken) or log errors. ValidateInputs ev -> do H.liftEffect $ Event.preventDefault ev { mailValidationForm } <- H.get let { login, token } = mailValidationForm case login, token of "", _ -> H.raise $ Log $ UnableToSend "Please, write your login." _, "" -> H.raise $ Log $ UnableToSend "Please, write your token." _, _ -> do case L.login login, T.token token of Left errors, _ -> H.raise $ Log $ UnableToSend $ show_error $ Login errors _, Left errors -> H.raise $ Log $ UnableToSend $ show_error $ Token errors Right _, Right _ -> handleAction $ SendMailValidationToken SendMailValidationToken -> do { mailValidationForm } <- H.get let { login, token } = mailValidationForm message <- H.liftEffect $ AuthD.serialize $ AuthD.MkValidateUser { user: login, activation_key: token } H.raise $ MessageToSend message H.raise $ Log $ SystemLog $ "Trying to validate email address of user \"" <> login <> "\"" show_error :: Error -> String show_error = case _ of Login arr -> "Error with the Login: " <> (A.fold $ map show_error_login arr) Token arr -> "Error with the Token: " <> (A.fold $ map show_error_token arr) show_error_login :: L.Error -> String show_error_login = case _ of -- L.ParsingError {error, position} -> -- "position " <> show position <> " " <> maybe "" string_error_login error L.ParsingError {error} -> maybe "" string_error_login error string_error_login :: L.LoginParsingError -> String string_error_login = case _ of L.CannotParse -> "cannot parse the login" L.CannotEntirelyParse -> "cannot entirely parse the login" L.Size min max n -> "login size should be between " <> show min <> " and " <> show max <> " (currently: " <> show n <> ")" show_error_token :: T.Error -> String show_error_token = case _ of -- T.ParsingError {error, position} -> -- "position " <> show position <> " " <> maybe "" string_error_token error T.ParsingError {error} -> maybe "" string_error_token error string_error_token :: T.TokenParsingError -> String string_error_token = case _ of T.CannotParse -> "cannot parse the token" T.CannotEntirelyParse -> "cannot entirely parse the token" T.Size min max n -> "token size should be between " <> show min <> " and " <> show max <> " (currently: " <> show n <> ")"