On Thursday, October 13, 2016 at 2:17:50 AM UTC+1, Fa Qing wrote:
> The PageLevel is calling the service level for a command. We want 
> intermediate effects, before the final command. But we don't want to just 
> issue intermediate commands either, because the state that is reacting to 
> the final command (the only one we have currently) could also be affected 
> by the intermediate command. Also, it doesn't help us refactor out the 
> (common) inputs into the service layer, such as a header value we need to 
> write out.
> It seems like there's a missing abstraction from the Elm architecture.


I decided to make an Auth module a special case, and not use the nested TEA 
architecture for it.

I have an API like this for Auth:

port module Auth exposing (..)

type alias Credentials =
    { username : String
    , password : String

login : Credentials -> Cmd msg
login authRequest =
    sendLogin authRequest

logout : Cmd msg
logout =
    sendLogout ()

unauthed : Cmd msg
unauthed =
    sendUnauthed ()

port sendLogin : Credentials -> Cmd msg
port sendLogout : () -> Cmd msg
port sendUnauthed : () -> Cmd msg

The ports I can use from anywhere in the application to login, logout or on 
a 403 unauthorized to set the global state to not logged in (unauthed).

The token is part of the state of the Auth module, which is linked in to 
the global state of the Main module of the application. All Msgs to 
sub-modules go through the update method of the Main module, and use the 
nested TEA and the 'lift' function from Material.Helpers to forwad them on 
the appropriate child module. Like this:

        AccountsMsg a ->
            lift .accounts (\m x -> { m | accounts = x }) AccountsMsg 
Accounts.State.update a model

Passes events for the Accounts module on to it.

This could easily be adapted to pass along the current Auth token.

Another way, perhaps more convenient, could be to hold the Auth token in 
'session storage' (not local storage as that would be insecure), and 
provide a global port in the Auth module to obtain it.

As Peter suggests, make all your API call functions take the token as an 
extra arg.

I didn't need that as I opted to use cookies, which means the browser does 
it for me. However, at some point I will need to deal with APIs that insist 
on tokens in the header. I think treating auth as a bit of a special case 
and using some ports to make it more easily global across the application 
feels right to me. It is not necessary though, there are other ways of 
doing 'out messages' whereby a child module sends a message to another 
child module without resorting to using ports.

You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to