Beispiel #1
0
// UpdateEntryWithEtag updates an entry in persistent storage in a way that
// detects concurrent modification. It also prevents users from modifying
// entries they do not own by returning ErrNoSuchId. t, the transaction,
// must be non nil.
func UpdateEntryWithEtag(
	store SafeUpdateEntryRunner,
	t db.Transaction,
	id int64,
	tag uint64,
	key *vsafe.Key,
	update functional.Filterer) error {
	if t == nil {
		panic("Transaction must be non-nil")
	}
	var origEntry vsafe.EntryWithEtag
	err := EntryByIdWithEtag(store, t, id, key, &origEntry)
	if err != nil {
		return err
	}
	err = update.Filter(&origEntry.Entry)
	if err == functional.Skipped {
		return nil
	}
	if err != nil {
		return err
	}
	if tag != origEntry.Etag {
		return ErrConcurrentModification
	}
	origEntry.Id = id
	return UpdateEntry(store, t, key, &origEntry.Entry)
}
Beispiel #2
0
func (h *Handler) doPost(w http.ResponseWriter, r *http.Request, id int64) {
	var err error
	session := common.GetUserSession(r)
	if !common.VerifyXsrfToken(r, kSingle) {
		err = common.ErrXsrf
	} else if http_util.HasParam(r.Form, "delete") {
		if isIdValid(id) {
			err = h.Store.RemoveEntry(nil, id, session.User.GetOwner())
		}
	} else if http_util.HasParam(r.Form, "cancel") {
		// Do nothing
	} else {
		var mutation functional.Filterer
		mutation, err = toEntry(r.Form)
		if err == nil {
			if isIdValid(id) {
				tag, _ := strconv.ParseUint(r.Form.Get("etag"), 10, 64)
				err = h.Doer.Do(func(t db.Transaction) error {
					return vsafedb.UpdateEntryWithEtag(
						h.Store, t, id, tag, session.Key(), mutation)
				})
			} else {
				var newId int64
				var entry vsafe.Entry
				mutation.Filter(&entry)
				newId, err = vsafedb.AddEntry(h.Store, nil, session.Key(), &entry)
				if err == nil {
					id = newId
				}
			}
		}
	}
	if err == vsafedb.ErrConcurrentModification {
		err = errors.New("Someone else updated this entry after you started. Click cancel and try again.")
	}
	if err != nil {
		http_util.WriteTemplate(
			w,
			kTemplate,
			newView(
				r.Form,
				isIdValid(id),
				session.Key().Id,
				common.NewXsrfToken(r, kSingle),
				err))
	} else {
		goBack(w, r, id)
	}
}