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  }