Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
91 lines
2.3 KiB
Go
91 lines
2.3 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
tea "charm.land/bubbletea/v2"
|
|
|
|
"git.kebcloud.no/keb/lazysecrets/internal/provider"
|
|
"git.kebcloud.no/keb/lazysecrets/internal/ui/panes"
|
|
)
|
|
|
|
// On a provider's row, the fourth pane describes its account: the fields
|
|
// the provider knows locally, then the groups the account is in, loaded
|
|
// once a session when first shown.
|
|
|
|
type groupsState struct {
|
|
names []string
|
|
err error
|
|
loading bool
|
|
}
|
|
|
|
type groupsMsg struct {
|
|
provider string
|
|
names []string
|
|
err error
|
|
}
|
|
|
|
// syncSourceDetail fills the pane for the selected row, loading the
|
|
// account's groups the first time.
|
|
func (m *Model) syncSourceDetail() tea.Cmd {
|
|
acct, ok := m.selectedAccount()
|
|
if !ok {
|
|
m.srcDetail.Set("", nil)
|
|
return nil
|
|
}
|
|
r, _ := m.sources.Selected()
|
|
var fields []panes.Field
|
|
for _, f := range acct.Fields {
|
|
fields = append(fields, panes.Field{Label: f.Label, Value: f.Value})
|
|
}
|
|
var cmd tea.Cmd
|
|
if g, ok := m.byID[r.provider].(provider.AccountGroups); ok {
|
|
st, seen := m.groups[r.provider]
|
|
if !seen {
|
|
st = groupsState{loading: true}
|
|
m.groups[r.provider] = st
|
|
id, timeout := r.provider, m.timeout
|
|
cmd = func() tea.Msg {
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
defer cancel()
|
|
names, err := g.Groups(ctx)
|
|
return groupsMsg{provider: id, names: names, err: err}
|
|
}
|
|
}
|
|
fields = append(fields, groupFields(st)...)
|
|
}
|
|
m.srcDetail.Set(m.byID[r.provider].Label(), fields)
|
|
return cmd
|
|
}
|
|
|
|
// fieldName names a copied field: its label, or for a group, the group.
|
|
func fieldName(f panes.Field) string {
|
|
if f.Label == "" || strings.HasPrefix(f.Label, "groups") {
|
|
return "group " + f.Value
|
|
}
|
|
return f.Label
|
|
}
|
|
|
|
// groupFields are the groups' rows: labelled on the first.
|
|
func groupFields(st groupsState) []panes.Field {
|
|
switch {
|
|
case st.loading:
|
|
return []panes.Field{{Label: "groups", Value: "loading…", Info: true}}
|
|
case errors.Is(st.err, provider.ErrUnsupported):
|
|
return nil
|
|
case st.err != nil:
|
|
return []panes.Field{{Label: "groups", Value: "couldn't list them: " + st.err.Error(), Info: true}}
|
|
case len(st.names) == 0:
|
|
return []panes.Field{{Label: "groups", Value: "none", Info: true}}
|
|
}
|
|
out := make([]panes.Field, len(st.names))
|
|
for i, n := range st.names {
|
|
out[i] = panes.Field{Value: n}
|
|
}
|
|
out[0].Label = fmt.Sprintf("groups %d", len(st.names))
|
|
return out
|
|
}
|