Пример #1
0
// 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)
	})
}
Пример #2
0
// 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)
	})
}
Пример #3
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)
}
Пример #4
0
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, "/")
}
Пример #5
0
// Returns true iff user is logged in.
func (c *Ctx) IsLoggedIn() bool {
	return session.Int(c.Req, "user_id", 0) != 0
}