// Redirects to LoginURL unless session value "user_id" is a nonzero integer. // // If "must_change_password" is set to true, any request for a path other than // ChangePasswordPath is redirected to that path. func MustLogin(h http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { userID := session.Int(req, "user_id", 0) if userID == 0 { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "You must log in to access this resource.", }) RedirectWithReturn(req, 302, LoginURL) return } mustChangePassword := session.Bool(req, "must_change_password", false) if mustChangePassword && req.URL.Path != ChangePasswordPath { session.AddFlash(req, session.Flash{ Severity: "success", Msg: "You must change your password before proceeding.", }) RedirectWithReturn(req, 302, ChangePasswordPath) return } h.ServeHTTP(rw, req) }) }
// Ensures that a user is not logged in. Session value "user_id" must be absent // or zero. If a user is logged in, redirects to AfterLoginURL. func MustNotLogin(h http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { userID := session.Int(req, "user_id", 0) if userID != 0 { ReturnRedirect(req, 302, AfterLoginURL) return } h.ServeHTTP(rw, req) }) }
func Auth_ChangePassword_POST(rw http.ResponseWriter, req *http.Request) { userID := session.Int(req, "user_id", 0) curPassword := req.PostFormValue("cur_password") password := req.PostFormValue("password") passwordConfirm := req.PostFormValue("password_confirm") if password == passwordConfirm { if len(password) >= 8 { mustChangePassword := session.Bool(req, "must_change_password", false) var err error var passwordPlain string if !mustChangePassword { err = GetBackend(req).GetDatabase().QueryRow("SELECT password_plain FROM \"n_user\" WHERE node_id=$1", userID).Scan(&passwordPlain) log.Panice(err) _, err = passlib.Verify(curPassword, passwordPlain) } if err == nil { newHash, err := passlib.Hash(password) log.Panice(err) newAK := make([]byte, 32) rand.Read(newAK) _, err = GetBackend(req).GetDatabase().Exec("UPDATE \"n_user\" SET password_plain=$1, ak=$2 WHERE node_id=$3", newHash, newAK, userID) log.Panice(err) session.Set(req, "user_ak", newAK) if mustChangePassword { session.Set(req, "must_change_password", false) } session.AddFlash(req, session.Flash{ Severity: "success", Msg: "Password changed.", }) miscctx.SeeOther(req, "/") return } else { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "Password incorrect.", }) } } else { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "Password must be at least 8 characters long.", }) } } else { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "Passwords do not match.", }) } Auth_ChangePassword_GET(rw, req) }
func Auth_ChangeEmail_POST(rw http.ResponseWriter, req *http.Request) { userID := session.Int(req, "user_id", 0) curPassword := req.PostFormValue("cur_password") email := req.PostFormValue("email") addr, err := mail.ParseAddress(email) if err != nil || addr.Name != "" { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "Invalid e. mail address.", }) Auth_ChangeEmail_GET(rw, req) return } var passwordPlain string var oldEmail string tx, err := GetBackend(req).GetDatabase().Begin() log.Panice(err) defer tx.Rollback() err = tx.QueryRow("SELECT password_plain, email FROM \"n_user\" WHERE node_id=$1 LIMIT 1", userID). Scan(&passwordPlain, &oldEmail) log.Panice(err) _, err = passlib.Verify(curPassword, passwordPlain) if err != nil { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "Passwords do not match.", }) Auth_ChangeEmail_GET(rw, req) return } //_, err = tx.Exec("INSERT INTO security_log (type,user_id,message) VALUES ($1,$2,$3)", "change_email", userID, fmt.Sprintf("%s -> %s", oldEmail, addr.Address)) //log.Panice(err) _, err = tx.Exec("UPDATE \"n_user\" SET email=$1, email_verified='f' WHERE node_id=$2", addr.Address, userID) if err != nil { if perr, ok := err.(pgx.PgError); ok && perr.Code == "23505" { // unique constraint violation session.AddFlash(req, session.Flash{ Severity: "error", Msg: "That e. mail address is already in use.", }) Auth_ChangeEmail_GET(rw, req) return } else { log.Panice(err) } } ak, _ := session.Get(req, "user_ak") err = sendVerificationEmail(addr.Address, ak.([]byte), false) log.Panice(err) err = tx.Commit() log.Panice(err) session.AddFlash(req, session.Flash{ Severity: "success", Msg: "E. mail address changed.", }) miscctx.SeeOther(req, "/") }
// Returns true iff user is logged in. func (c *Ctx) IsLoggedIn() bool { return session.Int(c.Req, "user_id", 0) != 0 }