dwyl / app-mvp-elm

:palm_tree: The Elm MVP @dwyl application
https://app-mvp-elm.herokuapp.com/
GNU General Public License v3.0
7 stars 0 forks source link

Saving user session in local storage #10

Open SimonLab opened 4 years ago

SimonLab commented 4 years ago

Now that the application receives a jwt on authentication we can start to manage the user session in a Elm model.

SimonLab commented 4 years ago

When the elm application is initialised we can pass the user information stored in local storage as flag:

       <script>
            flags = localStorage.getItem('store'); // get the value linked to the key "store"

            Elm.Main.init({flags: flags});
        </script>

localStorage is saving key/value data where the data represent the person information as a stringify json. You can use the functions setItem and removeItem to manage the data in local storage.

On the Elm side, the init function will now takes a flag parameter:

init : Maybe String -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )

Here the flag is represented as a Maybe String. So the value can be Nothing i.e. localStorage.getItem returns null or Just str where str represents the stringify json.

From there we can decode the flag to a specific Elm type. I've decided to represent a session with:

type Session = Guest | Session Person

type alias Person = {email: String, token: String}

The session can be a guest or a person.

Then in the init function we can use json decoder to match the Session type values:

       session =
            case flag of
                Nothing ->
                    Guest

                Just str ->
                    case decodeString (map2 Person (field "email" string) (field "token" string)) str of
                        Ok p ->
                            Session.Session p

                        _ ->
                            Session.Guest

It tooks me a bit of time to manage to decode the flag to this type. I'm still not sure this is the best solution, however it works. If the string stored in the local storage can't be decoded to the type (wrong json, doesn't contain email or token fields, not a valid json...) the application will convert the person to a Guest.

see also

SimonLab commented 4 years ago

I'm currently working on redirecting the user after authentication to a specific page (home page in my case but this can be change easily for example if we want to display a profile page on authentication).

Elm provide the Nav.replaceUrl function: image

We can see this function take as first parameter a Nav.Key value: image

At the moment this key is stored on the main model: https://github.com/dwyl/app-mvp-elm/blob/f33382bd34dc13211b801afa87e7daa60fd145cf/src/Main.elm#L40-L43

This is an issue when I try to redirect from a specific page as I don't have access to this value:

We can see that all the pages' model contain a session. So a solution to have access to the Nav.Key value is to store it in the session model. This will allow us to manage navigation more easily. We can for example redefine the model as:

type Session
    = Guest Nav.Key
    | Session Nav.Key Person
SimonLab commented 4 years ago

The session is now working on localhost (ie login, logout, redirects to home page...) and I'm now making sure that the backend apis are also up to date. At the moment the redirection to the home page after login is not working as there is an error while getting the user information with the apis hosted on Heorku (I just need to deploy the latest version of the app). So at the moment I'm getting back a 404 response. When receiving an error from the api (404, 401 or 500) we should redirect on the elm side the user to the correct error page. So we need to update the following part of the code to redirect the user: https://github.com/dwyl/app-mvp-elm/blob/6eb47dd75afdbbffeb5a73086ad1a2ca098a2425/src/Pages/Session.elm#L52-L54