2

I would like add "guards" to certain urls. These urls should only be accessed when the user is logged in. If not logged in i want to redirect the user to the login page. After a successful login i want the user to be "redirected" to the original hash.

This is my router

@dom
def outlet: Binding[Node] = {
    <div>{
    route.state.bind match {
        case s: View if UserService.hasRole("admin") => s.render.bind
        case s  if !UserService.isLoggedIn() => loginPage.render(Some(s.hash)).bind
        case _ => <div>Unknown</div>
    }
    }</div> 

The loginPage then changes the window hash after a successful login:

def login(username: String, password:String, orginalHash: Option[String]) =
    UserService.login(username,password).andThen{
        case Success(v) =>
            println(s"changing hash to $orginalHash")
            orginalHash.map(_.substring(1)).foreach(window.location.hash=_)
        case Failure(e) => message.value = "Wrong username/password"
    }

However i guess because the hash in fact does not change, it does not update the page:

  • Say i go to /index.html/#/foobar
  • The "guard" kicks in and the login page is shown (url remains /index.html/#/foobar)
  • Value of the orginalHash is #/foobar
  • changing the location.hash to /foobar does nothing

Is there a way to manipulate the router. Is there perhaps an api to change the current page?

raphaëλ
  • 6,393
  • 2
  • 29
  • 35

2 Answers2

3

You are creating a data-binding application, however some mutable states are not bindable in your system.

You should make UserService.isLoggedIn and UserService.hasRole("admin") be bindable.

Yang Bo
  • 3,586
  • 3
  • 22
  • 35
  • tried making a `val user: Var[Option[User]]` and change its value while using it in the pattern match guards , but does not help. I might just use a url query string instead. – raphaëλ Jun 26 '18 at 06:24
2

Thanks to directions from @yang-bo i solved it by using a val user: Var[Option[User]] inside UserService and changing the pattern match to

@dom
def outlet: Binding[Node] = {
    <div>{
        (route.state.bind, UserService.user.bind) match {
        case (s: View, Some(_))  => s.render.bind
        case (s, None) => loginPage.render(Some(s.hash)).bind
        case (_,_) => <div>Unknown</div>
    }
    }</div>
}
raphaëλ
  • 6,393
  • 2
  • 29
  • 35