Пример #1
0
// ACLSet is used to create or update an ACL entry
// allowCreate is used for initialization of the anonymous and master tokens,
// since it permits them to be created with a specified ID that does not exist.
func (s *StateStore) ACLSet(index uint64, acl *structs.ACL, allowCreate bool) error {
	// Start a new txn
	tx, err := s.tables.StartTxn(false)
	if err != nil {
		return err
	}
	defer tx.Abort()

	// Generate a new session ID
	if acl.ID == "" {
		for {
			acl.ID = generateUUID()
			res, err := s.aclTable.GetTxn(tx, "id", acl.ID)
			if err != nil {
				return err
			}
			// Quit if this ID is unique
			if len(res) == 0 {
				break
			}
		}
		acl.CreateIndex = index
		acl.ModifyIndex = index

	} else {
		// Look for the existing node
		res, err := s.aclTable.GetTxn(tx, "id", acl.ID)
		if err != nil {
			return err
		}

		switch len(res) {
		case 0:
			if !allowCreate {
				return fmt.Errorf("Invalid ACL")
			}
			acl.CreateIndex = index
			acl.ModifyIndex = index
		case 1:
			exist := res[0].(*structs.ACL)
			acl.CreateIndex = exist.CreateIndex
			acl.ModifyIndex = index
		default:
			panic(fmt.Errorf("Duplicate ACL definition. Internal error"))
		}
	}

	// Insert the ACL
	if err := s.aclTable.InsertTxn(tx, acl); err != nil {
		return err
	}

	// Trigger the update notifications
	if err := s.aclTable.SetLastIndexTxn(tx, index); err != nil {
		return err
	}
	tx.Defer(func() { s.watch[s.aclTable].Notify() })
	return tx.Commit()
}