简体   繁体   中英

Login in a multi-page website (SAFE Stack)

Does anybody use the Elmish routing for a multi-page app (SAFE Stack in my case) as specified by Maxime Mangel here on StackOverflow , but with a login page?

Do you, at the same time, use the accessibility ( Anonymous/LoggedIn ) philosophy as specified here in the Elmish Book ?

If so, you probably use different coding than in the Elmish Book (as I do), but in any case you probably need to have login results available in the main page (Main.fs) to implement the accessibility logic. The Elmish Book uses (in Login.fs) a function with an active pattern let (|UserLoggedIn|_|) =... and this function is called from the main or home page ( see here ).

But it wouldn't work in my app.

So my question is:

How do you transfer login results from the login page (Login.fs) into the main page (Main.fs)?

You can easily spot my login results here in the code:

Login.fs //client

let update (msg: Msg) (model: Model) : Model * Cmd<Msg> =

    match msg with
    | SetUsrInput value -> { model with InputUsr = value }, Cmd.none
    | SetPswInput value -> { model with InputPsw = value }, Cmd.none
    | SendUsrPswToServer ->
        let buttonClickEvent = SharedLoginValues.create model.InputUsr model.InputPsw
        let cmd = Cmd.OfAsync.perform getLoginApi.login buttonClickEvent GetLoginResults 
        model, cmd   
    | GetLoginResults value -> 
        let result =           
            match value with
            | SharedApi.UsernameOrPasswordIncorrect    -> { model with User = ApplicationUser.Anonymous}
            | SharedApi.LoggedIn user ->                  { model with User = ApplicationUser.LoggedIn user}     
        result, Cmd.ofMsg AskServerForSecurityTokenFile

Meanwhile, I use a workaround with reaching login results that I save on the server. Although the accesibility logic works as expected, the workaround seems to be cumbersome - I already have the login results in the login page so why reaching them twice...

Here, it is my code for the accesibility logic in Main.fs that should use the login results. By the way, the code is, to my big surprise, much simpler than that in the Elmish Book.

Main.fs //client

let private setRoute (optRoute: RouterM.Route option) model = 
                                             
    let model =
        let applicationUser = 
            //model.GetSecurityTokenFile -> this is the workaround
            // - results from the login page should be matched here instead
            match model.GetSecurityTokenFile with
            | true  -> LoggedIn model.user
            | false -> Anonymous

        let currentRoute =
            //model.GetSecurityTokenFile -> this is the workaround
            // - results from the login page should be matched here instead
            match model.GetSecurityTokenFile with
            | true  -> optRoute
            | false -> Some RouterM.Route.Home //or to a login page

        {
            model with CurrentRoute = currentRoute
                                      User = applicationUser  
        }                          

Well, just 2x match and that's really all. Or have I missed anything here?

match optRoute with
//...some code       

| Some (RouterM.Route.CMSRozcestnik cmsRozcestnikId) ->               
    match model.User with
    | Anonymous ->  
               let (homeModel, homeCmd) = Home.init () //or Login.init      
               { model with ActivePage = Page.Home homeModel }, cmd2 HomeMsg homeCmd AskServerForDeletingSecurityTokenFile
    | LoggedIn user  ->
               let (cmsRozcestnikModel, cmsRozcestnikCmd) = CMSRozcestnik.init cmsRozcestnikId 
               { model with ActivePage = Page.CMSRozcestnik cmsRozcestnikModel }, Cmd.map CMSRozcestnikMsg cmsRozcestnikCmd 
    | _     -> let (homeModel, homeCmd) = Home.init () //or Login.init      
               { model with ActivePage = Page.Home homeModel }, cmd2 HomeMsg homeCmd AskServerForDeletingSecurityTokenFile  

If needed, the entire code is here on GitHub: https://github.com/MiroslavHustak/SAFE-Stack-simple-multipage-website-with-CMS-

I have received an answer to my question from Maxime Mangel via F# Slack. Look at the section "Make the child communicate with the parent" in the link below and pay attention to the message ExternalMsg . Then just implement the code into your system. It worked with my code. If interested, you can look at the code on GitHub (the link is in the question).

https://medium.com/@MangelMaxime/my-tips-for-working-with-elmish-ab8d193d52fd

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM