func Auth_Verify_GET(rw http.ResponseWriter, req *http.Request) { ac := req.FormValue("ac") reset_s := req.FormValue("r") email := req.FormValue("e") var userID int64 var ak []byte var verified bool var isAdmin bool err := GetBackend(req).GetDatabase().QueryRow("SELECT node_id, ak, is_admin, email_verified FROM \"n_user\" WHERE email=$1 LIMIT 1", email).Scan(&userID, &ak, &isAdmin, &verified) log.Panice(err, "find ak for e. mail verify") if !webac.VerifyFor("verify-email/"+reset_s+"/"+email, ac, ak) { rw.WriteHeader(400) tpl.MustShow(req, "front/400", nil) return } if !verified { _, err = dbutil.UpdateKV(GetBackend(req).GetDatabase(), "n_user", dbutil.Set{"email_verified": true}, dbutil.Where{"node_id": userID}) log.Panice(err) } if reset_s == "1" { _, err = rand.Read(ak) log.Panice(err) _, err = dbutil.UpdateKV(GetBackend(req).GetDatabase(), "n_user", dbutil.Set{"ak": ak}, dbutil.Where{"node_id": userID}) } // log user in if reset_s == "0" { if verified { // non-reset links cannot be used to get a free login to an already-verified account rw.WriteHeader(400) tpl.MustShow(req, "front/400", nil) return } session.AddFlash(req, session.Flash{ Severity: "success", Msg: "Your e. mail address has been verified.", }) } else { session.Set(req, "must_change_password", true) } session.Set(req, "user_id", int(userID)) session.Set(req, "user_ak", ak) session.Set(req, "user_is_admin", isAdmin) session.Bump(req) miscctx.SeeOther(req, "/panel") }
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, "/") }
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_Register_POST(rw http.ResponseWriter, req *http.Request) { username := strings.TrimSpace(req.PostFormValue("username")) email := req.PostFormValue("email") password := req.PostFormValue("password") passwordConfirm := req.PostFormValue("password_confirm") if registerCAPTCHAFlag.Value() { ct, ok := session.Get(req, "captchaTime") if !ok || !solvedRecently(ct.(time.Time)) { captchaValue := req.PostFormValue("captcha") captchaKey := req.PostFormValue("captchak") captchaInstance, err := GetBackend(req).GetCAPTCHA().DecodeInstance(captchaKey) if err != nil || !GetBackend(req).GetCAPTCHA().Verify(captchaInstance, captchaValue) { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "Invalid CAPTCHA.", }) Auth_Register_GET(rw, req) return } session.Set(req, "captchaTime", time.Now()) } } username = strings.Trim(username, " \t\r\n") if username == "" { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "You must specify a username.", }) Auth_Register_GET(rw, req) return } if !re_validUsername.MatchString(username) { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "Usernames must consist of letters, numbers, underscores and dashes, must begin with a letter and must not exceed 32 characters.", }) Auth_Register_GET(rw, req) return } addr, err := mail.ParseAddress(email) if err != nil || addr.Name != "" { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "You must specify a valid e. mail address.", }) Auth_Register_GET(rw, req) return } if len(password) < 8 { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "Password must be at least eight characters long.", }) Auth_Register_GET(rw, req) return } if password != passwordConfirm { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "Passwords do not match.", }) Auth_Register_GET(rw, req) return } tx, err := GetBackend(req).GetDatabase().Begin() log.Panice(err) defer tx.Rollback() ak := make([]byte, 32) rand.Read(ak) pwhash, err := passlib.Hash(password) log.Panice(err) sn := shortname(username) var userID int64 err = dbutil.InsertKVR(tx, "node", "node_id", "shortname", sn, "longname", username, "type", "user", ).Scan(&userID) if err != nil { log.Debuge(err, "can't insert user node") if dbutil.IsUniqueViolation(err) { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "Username already in use.", }) } else { log.Panice(err) } Auth_Register_GET(rw, req) return } _, err = dbutil.InsertKV(tx, "n_user", "node_id", userID, "email", addr.Address, "password_plain", pwhash, "ak", ak, ) if err != nil { log.Debuge(err, "can't insert user") if dbutil.IsUniqueViolation(err) { session.AddFlash(req, session.Flash{ Severity: "error", Msg: "E. mail address already in use.", }) } else { log.Panice(err) } Auth_Register_GET(rw, req) return } err = tx.Commit() if err != nil { log.Errore(err, "commit registration transaction") Auth_Register_GET(rw, req) return } err = sendVerificationEmail(addr.Address, ak, false) if err != nil { log.Errore(err, "cannot send verification e. mail") Auth_Register_GET(rw, req) return } session.Set(req, "user_id", int(userID)) session.Set(req, "user_ak", ak) session.Set(req, "user_is_admin", false) session.AddFlash(req, session.Flash{ Severity: "success", Msg: "You have successfully been signed up.", }) miscctx.SeeOther(req, "/") return }