// If there is one key, asking to remove it will ask for confirmation. Passing // 'yes'/'y' response will continue the deletion. func TestRemoveOneKeyConfirm(t *testing.T) { setUp(t) yesses := []string{"yes", " Y "} for _, yesAnswer := range yesses { store := trustmanager.NewKeyMemoryStore(ret) key, err := utils.GenerateED25519Key(rand.Reader) require.NoError(t, err) err = store.AddKey(trustmanager.KeyInfo{Role: data.CanonicalRootRole, Gun: ""}, key) require.NoError(t, err) var out bytes.Buffer in := bytes.NewBuffer([]byte(yesAnswer + "\n")) err = removeKeyInteractively( []trustmanager.KeyStore{store}, key.ID(), in, &out) require.NoError(t, err) text, err := ioutil.ReadAll(&out) require.NoError(t, err) output := string(text) require.Contains(t, output, "Are you sure") require.Contains(t, output, "Deleted "+key.ID()) require.Len(t, store.ListKeys(), 0) } }
// If there is one key, asking to remove it will ask for confirmation. Passing // anything other than 'yes'/'y'/'' response will abort the deletion and // not delete the key. func TestRemoveOneKeyAbort(t *testing.T) { setUp(t) nos := []string{"no", "NO", "AAAARGH", " N "} store := trustmanager.NewKeyMemoryStore(ret) key, err := utils.GenerateED25519Key(rand.Reader) require.NoError(t, err) err = store.AddKey(trustmanager.KeyInfo{Role: data.CanonicalRootRole, Gun: ""}, key) require.NoError(t, err) stores := []trustmanager.KeyStore{store} for _, noAnswer := range nos { var out bytes.Buffer in := bytes.NewBuffer([]byte(noAnswer + "\n")) err := removeKeyInteractively(stores, key.ID(), in, &out) require.NoError(t, err) text, err := ioutil.ReadAll(&out) require.NoError(t, err) output := string(text) require.Contains(t, output, "Are you sure") require.Contains(t, output, "Aborting action") require.Len(t, store.ListKeys(), 1) } }
func removeKeyInteractively(keyStores []trustmanager.KeyStore, keyID string, in io.Reader, out io.Writer) error { var foundKeys [][]string var storesByIndex []trustmanager.KeyStore for _, store := range keyStores { for keypath, keyInfo := range store.ListKeys() { if filepath.Base(keypath) == keyID { foundKeys = append(foundKeys, []string{keypath, keyInfo.Role, store.Name()}) storesByIndex = append(storesByIndex, store) } } } if len(foundKeys) == 0 { return fmt.Errorf("No key with ID %s found", keyID) } if len(foundKeys) > 1 { for { // ask the user for which key to delete fmt.Fprintf(out, "Found the following matching keys:\n") for i, info := range foundKeys { fmt.Fprintf(out, "\t%d. %s: %s (%s)\n", i+1, info[0], info[1], info[2]) } fmt.Fprint(out, "Which would you like to delete? Please enter a number: ") var result string if _, err := fmt.Fscanln(in, &result); err != nil { return err } index, err := strconv.Atoi(strings.TrimSpace(result)) if err != nil || index > len(foundKeys) || index < 1 { fmt.Fprintf(out, "\nInvalid choice: %s\n", string(result)) continue } foundKeys = [][]string{foundKeys[index-1]} storesByIndex = []trustmanager.KeyStore{storesByIndex[index-1]} fmt.Fprintln(out, "") break } } // Now the length must be 1 - ask for confirmation. keyDescription := fmt.Sprintf("%s (role %s) from %s", foundKeys[0][0], foundKeys[0][1], foundKeys[0][2]) fmt.Fprintf(out, "Are you sure you want to remove %s? (yes/no) ", keyDescription) if !askConfirm(in) { fmt.Fprintln(out, "\nAborting action.") return nil } if err := storesByIndex[0].RemoveKey(foundKeys[0][0]); err != nil { return err } fmt.Fprintf(out, "\nDeleted %s.\n", keyDescription) return nil }