// This is a URL attached to ^login/?$ because then we can // programmatically log in the user and also check if the user is // login-able. Eventually userLogin will create a session row in the // database and send the sessionid key back to the requester. func UserLogin(self *ss.AppServer, w http.ResponseWriter, req *http.Request) error { errorhandler := func(w http.ResponseWriter, req *http.Request, err error) {} successhandler := func(w http.ResponseWriter, req *http.Request) {} userdata := new(ss.User) switch req.Header.Get("Content-type") { case "application/x-www-form-urlencoded": userdata.Password = req.FormValue("password") userdata.Username = req.FormValue("username") errorhandler = func(w http.ResponseWriter, req *http.Request, err error) { http.Redirect(w, req, "/loginfail/", http.StatusSeeOther) } successhandler = func(w http.ResponseWriter, req *http.Request) { http.Redirect(w, req, "/user/", http.StatusSeeOther) } case "application/json": // We retrieve the JSON string and encode it into the proper JSON // request struct. json_dec := json.NewDecoder(req.Body) err := json_dec.Decode(&userdata) if err != nil { logfile.Println(err) return err } errorhandler = func(w http.ResponseWriter, req *http.Request, err error) { ss.SendJSONError(w, err) } successhandler = func(w http.ResponseWriter, req *http.Request) { ss.SendJSON(w, true) } } if ok, err := Login(userdata); !ok { errorhandler(w, req, err) return err } session, err := ss.CreateMySQLSession() if err != nil { fmt.Println("Error creating cookie: " + err.Error()) } else { session.Add("user", userdata.Username) http.SetCookie(w, &http.Cookie{ Name: "session", Value: string(session.Key), Domain: req.Host, Path: "/", Expires: time.Now().Add(24 * time.Hour), }) } successhandler(w, req) return nil }
// Checks if the user is a valid user. If the user is not, then we // will tell the user ourselves and return false. We return the error // message ourself because other with we would have a string return // type or multiple return types which need to be parsed out or error // checks on them and this seems cleaner. func Login(userdata *ss.User) (bool, error) { h := sha512.New() io.WriteString(h, userdata.Username) io.WriteString(h, userdata.Password) userdata.Password = fmt.Sprintf("%x", h.Sum(nil)) row, err := ss.GetUser(userdata.Username) if err != nil { log.Println(err) return false, err } // Create a User instance from the SQL Results. req_user := ss.User{ row.Str(1), row.Str(2), } // if we've got here, we either are logged in or not. success := *userdata == req_user if !success { log.Println(ss.LoginError) return success, ss.LoginError } log.Printf("%s logged in.\n", req_user.Username) return success, nil }