From 6eb47dd75afdbbffeb5a73086ad1a2ca098a2425 Mon Sep 17 00:00:00 2001 From: SimonLab Date: Thu, 5 Mar 2020 12:17:00 +0100 Subject: [PATCH] manage sessions: login/logout, #10 --- elm.js | 349 ++++++++++++++++++++++++++++++++---------- index.html | 25 ++- src/Main.elm | 18 ++- src/Pages/Auth.elm | 13 +- src/Pages/Home.elm | 20 ++- src/Pages/Session.elm | 42 ++--- src/Route.elm | 5 + src/Session.elm | 64 +++++++- 8 files changed, 420 insertions(+), 116 deletions(-) diff --git a/elm.js b/elm.js index 3658a4f..2e3ef02 100644 --- a/elm.js +++ b/elm.js @@ -6014,6 +6014,7 @@ var $author$project$Route$Auth = function (a) { return {$: 'Auth', a: a}; }; var $author$project$Route$Home = {$: 'Home'}; +var $author$project$Route$Logout = {$: 'Logout'}; var $elm$url$Url$Parser$Parser = function (a) { return {$: 'Parser', a: a}; }; @@ -6195,7 +6196,11 @@ var $author$project$Route$routeParser = $elm$url$Url$Parser$oneOf( A2( $elm$url$Url$Parser$questionMark, $elm$url$Url$Parser$s('auth'), - $elm$url$Url$Parser$Query$string('jwt'))) + $elm$url$Url$Parser$Query$string('jwt'))), + A2( + $elm$url$Url$Parser$map, + $author$project$Route$Logout, + $elm$url$Url$Parser$s('logout')) ])); var $author$project$Route$fromUrl = function (url) { return A2($elm$url$Url$Parser$parse, $author$project$Route$routeParser, url); @@ -6590,7 +6595,7 @@ var $elm$http$Http$Header = F2( return {$: 'Header', a: a, b: b}; }); var $elm$http$Http$header = $elm$http$Http$Header; -var $author$project$Pages$Session$Person = F2( +var $author$project$Pages$Session$PersonInfo = F2( function (email, name) { return {email: email, name: name}; }); @@ -6599,7 +6604,7 @@ var $author$project$Pages$Session$personDecoder = A2( 'data', A3( $elm$json$Json$Decode$map2, - $author$project$Pages$Session$Person, + $author$project$Pages$Session$PersonInfo, A2($elm$json$Json$Decode$field, 'email', $elm$json$Json$Decode$string), A2($elm$json$Json$Decode$field, 'name', $elm$json$Json$Decode$string))); var $author$project$Endpoint$personInfo = A2( @@ -6628,6 +6633,22 @@ var $author$project$Pages$Session$init = F2( A2($author$project$Pages$Session$Model, session, token), $author$project$Pages$Session$getPersonInfo(token)); }); +var $elm$core$Maybe$destruct = F3( + function (_default, func, maybe) { + if (maybe.$ === 'Just') { + var a = maybe.a; + return func(a); + } else { + return _default; + } + }); +var $elm$json$Json$Encode$null = _Json_encodeNull; +var $author$project$Session$storeSession = _Platform_outgoingPort( + 'storeSession', + function ($) { + return A3($elm$core$Maybe$destruct, $elm$json$Json$Encode$null, $elm$core$Basics$identity, $); + }); +var $author$project$Session$logout = $author$project$Session$storeSession($elm$core$Maybe$Nothing); var $elm$core$Platform$Cmd$map = _Platform_map; var $author$project$Pages$Auth$toSession = function (model) { return model.session; @@ -6662,32 +6683,36 @@ var $author$project$Main$loadRoute = F2( $author$project$Main$NotFound(session), $elm$core$Platform$Cmd$none); } else { - if (maybeRoute.a.$ === 'Home') { - var _v1 = maybeRoute.a; - var _v2 = $author$project$Pages$Home$init(session); - var subModel = _v2.a; - var subMsg = _v2.b; - return _Utils_Tuple2( - $author$project$Main$Home(subModel), - A2($elm$core$Platform$Cmd$map, $author$project$Main$GotHomeMsg, subMsg)); - } else { - if (maybeRoute.a.a.$ === 'Nothing') { - var _v3 = maybeRoute.a.a; - var _v4 = $author$project$Pages$Auth$init(session); - var subModel = _v4.a; - var subMsg = _v4.b; + switch (maybeRoute.a.$) { + case 'Home': + var _v1 = maybeRoute.a; + var _v2 = $author$project$Pages$Home$init(session); + var subModel = _v2.a; + var subMsg = _v2.b; return _Utils_Tuple2( - $author$project$Main$Auth(subModel), - A2($elm$core$Platform$Cmd$map, $author$project$Main$GotAuthMsg, subMsg)); - } else { - var jwt = maybeRoute.a.a.a; - var _v5 = A2($author$project$Pages$Session$init, session, jwt); - var subModel = _v5.a; - var subMsg = _v5.b; - return _Utils_Tuple2( - $author$project$Main$Session(subModel), - A2($elm$core$Platform$Cmd$map, $author$project$Main$GotPagesSessionMsg, subMsg)); - } + $author$project$Main$Home(subModel), + A2($elm$core$Platform$Cmd$map, $author$project$Main$GotHomeMsg, subMsg)); + case 'Auth': + if (maybeRoute.a.a.$ === 'Nothing') { + var _v3 = maybeRoute.a.a; + var _v4 = $author$project$Pages$Auth$init(session); + var subModel = _v4.a; + var subMsg = _v4.b; + return _Utils_Tuple2( + $author$project$Main$Auth(subModel), + A2($elm$core$Platform$Cmd$map, $author$project$Main$GotAuthMsg, subMsg)); + } else { + var jwt = maybeRoute.a.a.a; + var _v5 = A2($author$project$Pages$Session$init, session, jwt); + var subModel = _v5.a; + var subMsg = _v5.b; + return _Utils_Tuple2( + $author$project$Main$Session(subModel), + A2($elm$core$Platform$Cmd$map, $author$project$Main$GotPagesSessionMsg, subMsg)); + } + default: + var _v6 = maybeRoute.a; + return _Utils_Tuple2(model, $author$project$Session$logout); } } }); @@ -6708,13 +6733,57 @@ var $author$project$Main$init = F3( }); var $elm$json$Json$Decode$null = _Json_decodeNull; var $elm$json$Json$Decode$oneOf = _Json_oneOf; +var $elm$core$Platform$Sub$map = _Platform_map; var $elm$core$Platform$Sub$batch = _Platform_batch; var $elm$core$Platform$Sub$none = $elm$core$Platform$Sub$batch(_List_Nil); -var $author$project$Main$subscriptions = function (_v0) { - return $elm$core$Platform$Sub$none; +var $author$project$Pages$Auth$GotSession = function (a) { + return {$: 'GotSession', a: a}; }; -var $elm$browser$Browser$Navigation$load = _Browser_load; -var $elm$browser$Browser$Navigation$pushUrl = _Browser_pushUrl; +var $elm$json$Json$Decode$decodeValue = _Json_run; +var $elm$core$Result$toMaybe = function (result) { + if (result.$ === 'Ok') { + var v = result.a; + return $elm$core$Maybe$Just(v); + } else { + return $elm$core$Maybe$Nothing; + } +}; +var $author$project$Session$decodeFromChange = F2( + function (decoder, val) { + return $elm$core$Result$toMaybe( + A2($elm$json$Json$Decode$decodeValue, decoder, val)); + }); +var $elm$json$Json$Decode$value = _Json_decodeValue; +var $author$project$Session$onSessionChange = _Platform_incomingPort('onSessionChange', $elm$json$Json$Decode$value); +var $author$project$Session$personDecoder = A3( + $elm$json$Json$Decode$map2, + $author$project$Session$Person, + A2($elm$json$Json$Decode$field, 'email', $elm$json$Json$Decode$string), + A2($elm$json$Json$Decode$field, 'token', $elm$json$Json$Decode$string)); +var $author$project$Session$changePerson = function (toMsg) { + return $author$project$Session$onSessionChange( + function (value) { + return toMsg( + A2($author$project$Session$decodeFromChange, $author$project$Session$personDecoder, value)); + }); +}; +var $author$project$Session$sessionFromPerson = F2( + function (maybePerson, key) { + if (maybePerson.$ === 'Just') { + var person = maybePerson.a; + return A2($author$project$Session$Session, key, person); + } else { + return $author$project$Session$Guest(key); + } + }); +var $author$project$Session$changeSession = F2( + function (toMsg, key) { + return $author$project$Session$changePerson( + function (maybePerson) { + return toMsg( + A2($author$project$Session$sessionFromPerson, maybePerson, key)); + }); + }); var $author$project$Session$navKey = function (session) { if (session.$ === 'Guest') { var key = session.a; @@ -6724,6 +6793,56 @@ var $author$project$Session$navKey = function (session) { return key; } }; +var $author$project$Pages$Auth$subscriptions = function (model) { + return A2( + $author$project$Session$changeSession, + $author$project$Pages$Auth$GotSession, + $author$project$Session$navKey(model.session)); +}; +var $author$project$Pages$Home$GotSession = function (a) { + return {$: 'GotSession', a: a}; +}; +var $author$project$Pages$Home$subscriptions = function (model) { + return A2( + $author$project$Session$changeSession, + $author$project$Pages$Home$GotSession, + $author$project$Session$navKey(model)); +}; +var $author$project$Pages$Session$GotSession = function (a) { + return {$: 'GotSession', a: a}; +}; +var $author$project$Pages$Session$subscriptions = function (model) { + return A2( + $author$project$Session$changeSession, + $author$project$Pages$Session$GotSession, + $author$project$Session$navKey(model.session)); +}; +var $author$project$Main$subscriptions = function (model) { + switch (model.$) { + case 'Home': + var home = model.a; + return A2( + $elm$core$Platform$Sub$map, + $author$project$Main$GotHomeMsg, + $author$project$Pages$Home$subscriptions(home)); + case 'Auth': + var authModel = model.a; + return A2( + $elm$core$Platform$Sub$map, + $author$project$Main$GotAuthMsg, + $author$project$Pages$Auth$subscriptions(authModel)); + case 'Session': + var sessionModel = model.a; + return A2( + $elm$core$Platform$Sub$map, + $author$project$Main$GotPagesSessionMsg, + $author$project$Pages$Session$subscriptions(sessionModel)); + default: + return $elm$core$Platform$Sub$none; + } +}; +var $elm$browser$Browser$Navigation$load = _Browser_load; +var $elm$browser$Browser$Navigation$pushUrl = _Browser_pushUrl; var $author$project$Main$toNavKey = function (model) { return $author$project$Session$navKey( $author$project$Main$toSession(model)); @@ -6772,37 +6891,21 @@ var $elm$url$Url$toString = function (url) { _Utils_ap(http, url.host)), url.path))); }; -var $author$project$Pages$Auth$update = F2( - function (msg, model) { - var result = msg.a; - if (result.$ === 'Ok') { - var urls = result.a; - return _Utils_Tuple2( - _Utils_update( - model, - {urls: urls}), - $elm$core$Platform$Cmd$none); - } else { - return _Utils_Tuple2(model, $elm$core$Platform$Cmd$none); - } - }); -var $author$project$Pages$Home$update = F2( - function (msg, model) { - return _Utils_Tuple2(model, $elm$core$Platform$Cmd$none); - }); -var $elm$core$Debug$log = _Debug_log; var $elm$browser$Browser$Navigation$replaceUrl = _Browser_replaceUrl; var $author$project$Route$routeToString = function (route) { - if (route.$ === 'Home') { - return '/'; - } else { - if (route.a.$ === 'Nothing') { - var _v1 = route.a; - return '/auth'; - } else { - var jwt = route.a.a; - return '/auth?jwt=' + jwt; - } + switch (route.$) { + case 'Home': + return '/'; + case 'Auth': + if (route.a.$ === 'Nothing') { + var _v1 = route.a; + return '/auth'; + } else { + var jwt = route.a.a; + return '/auth?jwt=' + jwt; + } + default: + return '/logout'; } }; var $author$project$Route$replaceUrl = F2( @@ -6812,22 +6915,96 @@ var $author$project$Route$replaceUrl = F2( key, $author$project$Route$routeToString(route)); }); -var $author$project$Pages$Session$update = F2( +var $author$project$Pages$Auth$update = F2( function (msg, model) { - var result = msg.a; - if (result.$ === 'Ok') { - var person = result.a; - var _v2 = A2($elm$core$Debug$log, 'Person', person); + if (msg.$ === 'GotAuthUrls') { + var result = msg.a; + if (result.$ === 'Ok') { + var urls = result.a; + return _Utils_Tuple2( + _Utils_update( + model, + {urls: urls}), + $elm$core$Platform$Cmd$none); + } else { + return _Utils_Tuple2(model, $elm$core$Platform$Cmd$none); + } + } else { + var session = msg.a; return _Utils_Tuple2( - model, + _Utils_update( + model, + {session: session}), A2( $author$project$Route$replaceUrl, $author$project$Session$navKey(model.session), $author$project$Route$Home)); + } + }); +var $elm$core$Debug$log = _Debug_log; +var $author$project$Pages$Home$update = F2( + function (msg, model) { + var session = msg.a; + var _v1 = A2($elm$core$Debug$log, 'new session', session); + return _Utils_Tuple2( + session, + A2( + $author$project$Route$replaceUrl, + $author$project$Session$navKey(model), + $author$project$Route$Home)); + }); +var $elm$json$Json$Encode$object = function (pairs) { + return _Json_wrap( + A3( + $elm$core$List$foldl, + F2( + function (_v0, obj) { + var k = _v0.a; + var v = _v0.b; + return A3(_Json_addField, k, v, obj); + }), + _Json_emptyObject(_Utils_Tuple0), + pairs)); +}; +var $elm$json$Json$Encode$string = _Json_wrap; +var $author$project$Session$encode = function (person) { + return $elm$json$Json$Encode$object( + _List_fromArray( + [ + _Utils_Tuple2( + 'email', + $elm$json$Json$Encode$string(person.email)), + _Utils_Tuple2( + 'token', + $elm$json$Json$Encode$string(person.token)) + ])); +}; +var $author$project$Pages$Session$update = F2( + function (msg, model) { + if (msg.$ === 'GotPersonInfo') { + var result = msg.a; + if (result.$ === 'Ok') { + var person = result.a; + var session = {email: person.email, token: model.token}; + return _Utils_Tuple2( + model, + $author$project$Session$storeSession( + $elm$core$Maybe$Just( + $author$project$Session$encode(session)))); + } else { + var e = result.a; + return _Utils_Tuple2(model, $elm$core$Platform$Cmd$none); + } } else { - var e = result.a; - var _v3 = A2($elm$core$Debug$log, 'Error', e); - return _Utils_Tuple2(model, $elm$core$Platform$Cmd$none); + var session = msg.a; + return _Utils_Tuple2( + _Utils_update( + model, + {session: session}), + A2( + $author$project$Route$replaceUrl, + $author$project$Session$navKey(model.session), + $author$project$Route$Home)); } }); var $author$project$Main$update = F2( @@ -6902,7 +7079,6 @@ var $author$project$Main$update = F2( return _Utils_Tuple2(model, $elm$core$Platform$Cmd$none); }); var $elm$html$Html$a = _VirtualDom_node('a'); -var $elm$json$Json$Encode$string = _Json_wrap; var $elm$html$Html$Attributes$stringProperty = F2( function (key, string) { return A2( @@ -7073,14 +7249,31 @@ var $author$project$Pages$Home$view = function (model) { } else { var person = model.b; return A2( - $elm$html$Html$span, - _List_fromArray( - [ - $elm$html$Html$Attributes$class('tc db') - ]), + $elm$html$Html$div, + _List_Nil, _List_fromArray( [ - $elm$html$Html$text('logged in with token: ' + person.email) + A2( + $elm$html$Html$span, + _List_fromArray( + [ + $elm$html$Html$Attributes$class('tc db') + ]), + _List_fromArray( + [ + $elm$html$Html$text('logged in with token: ' + person.email) + ])), + A2( + $elm$html$Html$a, + _List_fromArray( + [ + $author$project$Route$href($author$project$Route$Logout), + $elm$html$Html$Attributes$class('tc db') + ]), + _List_fromArray( + [ + $elm$html$Html$text('logout') + ])) ])); } }() @@ -7089,7 +7282,7 @@ var $author$project$Pages$Home$view = function (model) { }; }; var $elm$html$Html$p = _VirtualDom_node('p'); -var $author$project$Pages$Session$view = function (model) { +var $author$project$Pages$Session$view = function (_v0) { return { content: _List_fromArray( [ diff --git a/index.html b/index.html index a88f573..33d9e5e 100644 --- a/index.html +++ b/index.html @@ -15,8 +15,29 @@ This website is using Elm, so it needs js enabled diff --git a/src/Main.elm b/src/Main.elm index e850f71..1cc5ee6 100644 --- a/src/Main.elm +++ b/src/Main.elm @@ -144,10 +144,24 @@ loadRoute maybeRoute model = in ( Session subModel, Cmd.map GotPagesSessionMsg subMsg ) + Just Route.Logout -> + ( model, Session.logout ) + subscriptions : Model -> Sub Msg -subscriptions _ = - Sub.none +subscriptions model = + case model of + Home home -> + Sub.map GotHomeMsg (Home.subscriptions home) + + Auth authModel -> + Sub.map GotAuthMsg (Auth.subscriptions authModel) + + Session sessionModel -> + Sub.map GotPagesSessionMsg (PagesSession.subscriptions sessionModel) + + NotFound _ -> + Sub.none view : Model -> Browser.Document Msg diff --git a/src/Pages/Auth.elm b/src/Pages/Auth.elm index e5a29e0..e6978ff 100644 --- a/src/Pages/Auth.elm +++ b/src/Pages/Auth.elm @@ -1,4 +1,4 @@ -module Pages.Auth exposing (Model, Msg(..), TypeUrl(..), Url, authUrlsDecoder, getAuthUrls, init, showAuthUrl, toSession, update, urlDecoder, urlTypeDecoder, view) +module Pages.Auth exposing (Model, Msg(..), TypeUrl(..), Url, authUrlsDecoder, getAuthUrls, init, showAuthUrl, subscriptions, toSession, update, urlDecoder, urlTypeDecoder, view) import Asset exposing (..) import Endpoint @@ -43,6 +43,7 @@ init session = type Msg = GotAuthUrls (Result Http.Error (List Url)) + | GotSession Session update : Msg -> Model -> ( Model, Cmd msg ) @@ -56,6 +57,11 @@ update msg model = Err _ -> ( model, Cmd.none ) + GotSession session -> + ( { model | session = session } + , Route.replaceUrl (Session.navKey model.session) Route.Home + ) + -- View @@ -127,3 +133,8 @@ showAuthUrl url = toSession : Model -> Session toSession model = model.session + + +subscriptions : Model -> Sub Msg +subscriptions model = + Session.changeSession GotSession (Session.navKey model.session) diff --git a/src/Pages/Home.elm b/src/Pages/Home.elm index 32bfd52..a69db07 100644 --- a/src/Pages/Home.elm +++ b/src/Pages/Home.elm @@ -1,4 +1,4 @@ -module Pages.Home exposing (Model, Msg(..), init, toSession, update, view) +module Pages.Home exposing (Model, Msg(..), init, subscriptions, toSession, update, view) import Asset import Html exposing (..) @@ -26,14 +26,16 @@ init session = type Msg - = None + = GotSession Session update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of - None -> - ( model, Cmd.none ) + GotSession session -> + ( session + , Route.replaceUrl (Session.navKey model) Route.Home + ) @@ -51,7 +53,10 @@ view model = a [ Route.href (Route.Auth Nothing), class "tc db" ] [ text "login/signup" ] Session.Session _ person -> - span [ class "tc db" ] [ text <| "logged in with token: " ++ person.email ] + div [] + [ span [ class "tc db" ] [ text <| "logged in with: " ++ person.email ] + , a [ Route.href Route.Logout, class "tc db" ] [ text "logout" ] + ] ] } @@ -59,3 +64,8 @@ view model = toSession : Model -> Session toSession model = model + + +subscriptions : Model -> Sub Msg +subscriptions model = + Session.changeSession GotSession (Session.navKey model) diff --git a/src/Pages/Session.elm b/src/Pages/Session.elm index d2cbdd8..93b714a 100644 --- a/src/Pages/Session.elm +++ b/src/Pages/Session.elm @@ -1,4 +1,4 @@ -module Pages.Session exposing (Model, Msg(..), Person, getPersonInfo, init, personDecoder, subscriptions, toSession, update, view) +module Pages.Session exposing (Model, Msg(..), PersonInfo, getPersonInfo, init, personDecoder, subscriptions, toSession, update, view) import Asset import Endpoint @@ -8,7 +8,7 @@ import Http import Json.Decode as JD import Page import Route -import Session exposing (..) +import Session exposing (Session) type alias Model = @@ -17,7 +17,7 @@ type alias Model = } -type alias Person = +type alias PersonInfo = { email : String , name : String } @@ -33,7 +33,8 @@ init session token = type Msg - = GotPersonInfo (Result Http.Error Person) + = GotPersonInfo (Result Http.Error PersonInfo) + | GotSession Session update : Msg -> Model -> ( Model, Cmd Msg ) @@ -42,21 +43,21 @@ update msg model = GotPersonInfo result -> case result of Ok person -> - -- instead of Cmd.none, call a store cache command let - _ = - Debug.log "Person" person + session = + { email = person.email, token = model.token } in - ( model, Route.replaceUrl (navKey model.session) Route.Home ) + ( model, Session.storeSession (Just <| Session.encode session) ) -- if a 401 redirect to 401 page not authorised Err e -> - let - _ = - Debug.log "Error" e - in ( model, Cmd.none ) + GotSession session -> + ( { model | session = session } + , Route.replaceUrl (Session.navKey model.session) Route.Home + ) + getPersonInfo : String -> Cmd Msg getPersonInfo token = @@ -72,10 +73,10 @@ getPersonInfo token = } -personDecoder : JD.Decoder Person +personDecoder : JD.Decoder PersonInfo personDecoder = JD.field "data" - (JD.map2 Person + (JD.map2 PersonInfo (JD.field "email" JD.string) (JD.field "name" JD.string) ) @@ -86,7 +87,7 @@ personDecoder = view : Model -> Page.PageStructure Msg -view model = +view _ = { title = "Auth" , content = [ img [ Asset.src Asset.logo, class "center db pt2" ] [] @@ -101,18 +102,9 @@ view model = subscriptions : Model -> Sub Msg subscriptions model = - Sub.none + Session.changeSession GotSession (Session.navKey model.session) toSession : Model -> Session toSession model = model.session - - - --- create port module --- create storeSession --- in html.js store the session --- create subscriptions to listen to new change in store and trigger the GotSession session message --- redirect to Home page with the new session --- Create a redirect function in Route module diff --git a/src/Route.elm b/src/Route.elm index ceac86e..76f1989 100644 --- a/src/Route.elm +++ b/src/Route.elm @@ -15,6 +15,7 @@ import Url.Parser.Query as Query type Route = Home | Auth (Maybe String) + | Logout routeParser : Parser.Parser (Route -> a) a @@ -22,6 +23,7 @@ routeParser = Parser.oneOf [ Parser.map Home Parser.top , Parser.map Auth (Parser.s "auth" Query.string "jwt") + , Parser.map Logout (Parser.s "logout") ] @@ -47,6 +49,9 @@ routeToString route = Auth (Just jwt) -> "/auth?jwt=" ++ jwt + Logout -> + "/logout" + replaceUrl : Nav.Key -> Route -> Cmd msg replaceUrl key route = diff --git a/src/Session.elm b/src/Session.elm index c372deb..4973fc5 100644 --- a/src/Session.elm +++ b/src/Session.elm @@ -1,10 +1,11 @@ -module Session exposing (Person, Session(..), decode, navKey) +port module Session exposing (Person, Session(..), changeSession, decode, encode, logout, navKey, onSessionChange, storeSession) {-| Represent the current user -} import Browser.Navigation as Nav -import Json.Decode exposing (..) +import Json.Decode as JD +import Json.Encode as JE type Session @@ -20,7 +21,7 @@ type alias Person = decode : Nav.Key -> String -> Session decode key str = - case decodeString (map2 Person (field "email" string) (field "token" string)) str of + case JD.decodeString (JD.map2 Person (JD.field "email" JD.string) (JD.field "token" JD.string)) str of Ok p -> Session key p @@ -28,6 +29,14 @@ decode key str = Guest key +encode : Person -> JE.Value +encode person = + JE.object + [ ( "email", JE.string person.email ) + , ( "token", JE.string person.token ) + ] + + navKey : Session -> Nav.Key navKey session = case session of @@ -36,3 +45,52 @@ navKey session = Session key _ -> key + + +port storeSession : Maybe JD.Value -> Cmd msg + + +port onSessionChange : (JE.Value -> msg) -> Sub msg + + + +-- create function which use onSessionChange: pass transform value to maybe person +-- create change function which transform a maybe person to session + + +changeSession : (Session -> msg) -> Nav.Key -> Sub msg +changeSession toMsg key = + changePerson (\maybePerson -> toMsg (sessionFromPerson maybePerson key)) + + +changePerson : (Maybe Person -> msg) -> Sub msg +changePerson toMsg = + onSessionChange (\value -> toMsg (decodeFromChange personDecoder value)) + + +sessionFromPerson : Maybe Person -> Nav.Key -> Session +sessionFromPerson maybePerson key = + case maybePerson of + Just person -> + Session key person + + Nothing -> + Guest key + + +personDecoder : JD.Decoder Person +personDecoder = + JD.map2 Person + (JD.field "email" JD.string) + (JD.field "token" JD.string) + + +decodeFromChange : JD.Decoder Person -> JD.Value -> Maybe Person +decodeFromChange decoder val = + JD.decodeValue decoder val + |> Result.toMaybe + + +logout : Cmd msg +logout = + storeSession Nothing