github.com/bitcubate/cryptojournal@v1.2.5-0.20171102134152-f578b3d788ab/src/users/actions/login.go (about) 1 package useractions 2 3 import ( 4 "fmt" 5 "net/http" 6 7 "github.com/fragmenta/auth" 8 "github.com/fragmenta/mux" 9 "github.com/fragmenta/server" 10 "github.com/fragmenta/server/log" 11 "github.com/fragmenta/view" 12 13 "github.com/bitcubate/cryptojournal/src/lib/session" 14 "github.com/bitcubate/cryptojournal/src/users" 15 ) 16 17 // HandleLoginShow shows the page at /users/login 18 func HandleLoginShow(w http.ResponseWriter, r *http.Request) error { 19 20 // Check they're not logged in already. 21 if !session.CurrentUser(w, r).Anon() { 22 return server.Redirect(w, r, "/?warn=already_logged_in") 23 } 24 25 params, err := mux.Params(r) 26 if err != nil { 27 return server.NotFoundError(err) 28 } 29 30 // Show the login page, with login failure warnings. 31 view := view.NewRenderer(w, r) 32 switch params.Get("error") { 33 case "failed_email": 34 view.AddKey("warning", "Sorry, we couldn't find a user with that email.") 35 case "failed_password": 36 view.AddKey("warning", "Sorry, the password was incorrect, please try again.") 37 } 38 view.AddKey("hideSubmit", true) 39 return view.Render() 40 } 41 42 // HandleLogin responds to POST /users/login 43 // by setting a cookie on the request with encrypted user data. 44 func HandleLogin(w http.ResponseWriter, r *http.Request) error { 45 46 // Check the authenticity token 47 err := session.CheckAuthenticity(w, r) 48 if err != nil { 49 return err 50 } 51 52 // Check they're not logged in already if so redirect. 53 if !session.CurrentUser(w, r).Anon() { 54 return server.Redirect(w, r, "/?warn=already_logged_in") 55 } 56 57 // Get the user details from the database 58 params, err := mux.Params(r) 59 if err != nil { 60 return server.NotFoundError(err) 61 } 62 63 // Fetch the first user by EMAIL or username 64 email := params.Get("email") 65 66 // Find the user with this email 67 user, err := users.FindFirst("email=?", email) 68 if err != nil { 69 // If not found try by user.Name instead, error checked below 70 user, err = users.FindFirst("name=?", email) 71 } 72 73 if err != nil { 74 log.Info(log.V{"msg": "login failed", "email": email, "status": http.StatusNotFound}) 75 return server.Redirect(w, r, "/users/login?error=failed_email") 76 } 77 78 // Check password against the stored password 79 err = auth.CheckPassword(params.Get("password"), user.PasswordHash) 80 if err != nil { 81 log.Info(log.V{"msg": "login failed", "error": err, "email": email, "user_id": user.ID, "status": http.StatusUnauthorized}) 82 return server.Redirect(w, r, "/users/login?error=failed_password") 83 } 84 85 // Now save the user details in a secure cookie, 86 // so that we remember the next request 87 session, err := auth.Session(w, r) 88 if err != nil { 89 log.Info(log.V{"msg": "login failed", "email": email, "user_id": user.ID, "status": http.StatusInternalServerError}) 90 } 91 92 // Success, log it and set the cookie with user id 93 session.Set(auth.SessionUserKey, fmt.Sprintf("%d", user.ID)) 94 session.Save(w) 95 96 // Log action 97 log.Info(log.V{"msg": "login", "user_email": user.Email, "user_name": user.Name, "user_id": user.ID}) 98 99 // Redirect - ideally here we'd redirect to their original request path 100 return server.Redirect(w, r, "/") 101 }