91 lines
2 KiB
Go
91 lines
2 KiB
Go
package cli
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
frameworkcli "gitea.lclr.dev/AI/mcp-framework/cli"
|
|
|
|
"email-mcp/internal/secretstore"
|
|
)
|
|
|
|
type InteractiveConfigPrompter struct {
|
|
reader *bufio.Reader
|
|
stdinFile *os.File
|
|
output io.Writer
|
|
}
|
|
|
|
func NewInteractiveConfigPrompter(input io.Reader, output io.Writer) *InteractiveConfigPrompter {
|
|
if input == nil {
|
|
input = strings.NewReader("")
|
|
}
|
|
if output == nil {
|
|
output = io.Discard
|
|
}
|
|
|
|
prompter := &InteractiveConfigPrompter{
|
|
reader: bufio.NewReader(input),
|
|
output: output,
|
|
}
|
|
if file, ok := input.(*os.File); ok {
|
|
prompter.stdinFile = file
|
|
}
|
|
|
|
return prompter
|
|
}
|
|
|
|
func (p *InteractiveConfigPrompter) PromptCredential(_ context.Context, existing secretstore.Credential, hasStoredPassword bool) (secretstore.Credential, error) {
|
|
host, err := frameworkcli.PromptLine(p.reader, p.output, "IMAP host", existing.Host)
|
|
if err != nil {
|
|
return secretstore.Credential{}, err
|
|
}
|
|
|
|
username, err := frameworkcli.PromptLine(p.reader, p.output, "Username", existing.Username)
|
|
if err != nil {
|
|
return secretstore.Credential{}, err
|
|
}
|
|
|
|
password, err := p.promptPassword(existing.Password, hasStoredPassword)
|
|
if err != nil {
|
|
return secretstore.Credential{}, err
|
|
}
|
|
|
|
cred := secretstore.Credential{
|
|
Host: host,
|
|
Username: username,
|
|
Password: password,
|
|
}
|
|
if err := cred.Validate(); err != nil {
|
|
return secretstore.Credential{}, err
|
|
}
|
|
|
|
return cred, nil
|
|
}
|
|
|
|
func (p *InteractiveConfigPrompter) promptPassword(storedPassword string, hasStoredPassword bool) (string, error) {
|
|
if p.stdinFile != nil {
|
|
return frameworkcli.PromptSecret(p.stdinFile, p.output, "Password", hasStoredPassword, storedPassword)
|
|
}
|
|
|
|
if hasStoredPassword {
|
|
fmt.Fprint(p.output, "Password [stored, leave blank to keep]: ")
|
|
} else {
|
|
fmt.Fprint(p.output, "Password: ")
|
|
}
|
|
|
|
line, err := p.reader.ReadString('\n')
|
|
if err != nil && err != io.EOF {
|
|
return "", err
|
|
}
|
|
|
|
password := strings.TrimSpace(line)
|
|
if password == "" && hasStoredPassword {
|
|
return storedPassword, nil
|
|
}
|
|
|
|
return password, nil
|
|
}
|