Lock users after # of attempts.

36 views
Skip to first unread message

John Andrews

unread,
Mar 17, 2015, 12:30:59 PM3/17/15
to lif...@googlegroups.com
So I'm using MegaProtoUser for my Lift application. One thing I want to add is so that if a user tries to login incorrectly 5 times, that account would be locked (with the locked cleared manually or via some date/time function, etc)

To do this I already added a check to my Boot.Scala to check if a user was locked, but I'm trying to add the code that would actually trigger the lock.

I thought this would be simply done in object User extends User with MetaMegaProtoUser[User]

override def testPassword(toTest: Box[String]): Boolean = {
    // Update database of user login attempts
    // If value exceeds amount, set user to locked
    super.testPassword(toTest)
}

but despite checking the super method for getting the right override, I get the 'method overrides nothing' error. Is there a fix to this error (something I'm doing wrong) or am I totally off on where I should try to do this functionality?

Thank you for your time,
John

John Andrews

unread,
Mar 18, 2015, 10:58:50 AM3/18/15
to lif...@googlegroups.com
Okay so after doing some more digging it seems the only nice way to do this is overriding the login function itself - was trying to avoid that, but see attached for how to do this (if you have comments on things I should update - chime in)

override def login = {
 
if (S.post_?) {  
        S
.param("username").  
        flatMap
(username => getSingleton.find(By(email, username))) match {  
         
case Full(user) if user.validated.get &&  
               
!user.locked.get &&
                user
.password.match_?(S.param("password").openOr("*")) =>  
                S
.notice(S.?("logged.in"))  
                user
.loginAttempts(0).save()
                logUserIn
(user)  
                val redir
= loginRedirect.is match {  
                 
case Full(url) =>  
                        loginRedirect
(Empty)  
                        url  
                 
case _ =>  
                        homePage  
               
}  
                S
.redirectTo(redir)  

         
case Full(user) if !user.validated.get =>  
                S
.error(S.?("account.validation.error"))
               
         
case Full(user) if user.locked.get => {
                  S
.error("Account is Locked")
         
}
         
case Full(user) if !user.password.match_?(S.param("password").openOr("*")) => {
                  println
("Invalid Password, updating # of Login Attempts")
                 
var previousAttempts = user.loginAttempts.get
                  user
.loginAttempts(previousAttempts + 1).save()
                 
                 
if (previousAttempts + 1 > 2) {
                          user
.locked(true).save()
                 
}
                 
                  S
.error(S.?("invalid.credentials"))  
         
}
               
         
case _ => {
                  S
.error(S.?("invalid.credentials"))  
         
}
       
}  
 
}  

  bind
("user", loginXhtml,  
           
"email" -> (FocusOnLoad(<input type="text" name="username"/>)),  
           
"password" -> (<input type="password" name="password"/>),  
           
"submit" -> (<input type="submit" class="btn primary" value={S.?("log.in")}/>))  
}

Of course you'll need to add the Locked/Login Attempts fields, but otherwise here's a good starting point if others want to add functionality.

Antonio Salazar Cardozo

unread,
Mar 18, 2015, 3:50:14 PM3/18/15
to lif...@googlegroups.com
Thanks for reporting back… That does look like a lot of code, but I don't have much experience
with the built-in user stuff—but wanted to express appreciation that you shared your solution :)
Thanks,
Antonio

Torsten Uhlmann

unread,
Mar 19, 2015, 2:53:39 AM3/19/15
to lif...@googlegroups.com
I made the experience that the built in user management is great for small projects and great to get started quickly.

However it can get quiet complex if you try to poke holes in it and add your own stuff.
For more flexibility please have a look at mongo-auth [1] or mapper-auth [2] (a port of the former):


Torsten.

--
--
Lift, the simply functional web framework: http://liftweb.net
Code: http://github.com/lift
Discussion: http://groups.google.com/group/liftweb
Stuck? Help us help you: https://www.assembla.com/wiki/show/liftweb/Posting_example_code

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



--
AGYNAMIX(R). Passionate Software.
Inh. Torsten Uhlmann | Buchenweg 5 | 09380 Thalheim
Phone:     +49 3721 273445
Fax:         +49 3721 273446
Mobile:     +49 151 12412427
Web:        http://www.agynamix.de
Reply all
Reply to author
Forward
0 new messages