Пример #1
0
func Auth_Login_POST(rw http.ResponseWriter, req *http.Request) {
	email := req.PostFormValue("email")
	password := req.PostFormValue("password")
	userID, ak, isAdmin := ValidateUserEmailPassword(req, email, password)
	if userID == 0 {
		session.AddFlash(req, session.Flash{
			Severity: "error",
			Msg:      "Invalid e. mail address or password.",
		})
		Auth_Login_GET(rw, req)
		return
	}

	session.Set(req, "user_id", int(userID))
	session.Set(req, "user_ak", ak)
	session.Set(req, "user_is_admin", isAdmin)

	if req.PostFormValue("remember") != "" {
		session.Set(req, "session_lifetime", 90*24*time.Hour)
	}

	session.Bump(req)

	session.AddFlash(req, session.Flash{
		Severity: "success",
		Msg:      "You have been logged in.",
	})

	authz.ReturnRedirect(req, 302, authz.AfterLoginURL)
}
Пример #2
0
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")
}
Пример #3
0
// Get the action key to use in relation to a given request.
func GetAK(req *http.Request) []byte {
	// The key is for authenticated users a 32-byte random value stored for their
	// account. For anonymous users it is a 32-byte secret value, the first 16
	// bytes of which are XORed with the v6-mapped IP address. (currently not used)
	ak := session.Bytes(req, "user_ak", nil)
	if len(ak) == 0 {
		ak = make([]byte, 32)
		_, err := rand.Read(ak)
		if err != nil {
			panic(err)
		}

		session.Set(req, "user_ak", ak)
	}

	return ak
}
Пример #4
0
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)
}
Пример #5
0
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
}