mirror of
https://github.com/larksuite/cli.git
synced 2026-09-14 18:42:53 +08:00
fix: honor runtime credential sources in config views
Change-Id: I40b2ffedc5c1db5e08e86b9472ea2b84fa02bb29
This commit is contained in:
@@ -31,12 +31,7 @@ func NewCmdConfigDefaultAs(f *cmdutil.Factory) *cobra.Command {
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
current := app.DefaultAs
|
||||
if current == "" {
|
||||
current = "auto"
|
||||
}
|
||||
fmt.Fprintf(f.IOStreams.Out, "default-as: %s\n", current)
|
||||
return nil
|
||||
return showDefaultAs(f, app)
|
||||
}
|
||||
|
||||
value := args[0]
|
||||
@@ -54,3 +49,20 @@ func NewCmdConfigDefaultAs(f *cmdutil.Factory) *cobra.Command {
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func showDefaultAs(f *cmdutil.Factory, app *core.AppConfig) error {
|
||||
current := ""
|
||||
if f != nil && f.Config != nil {
|
||||
if cfg, err := f.Config(); err == nil && cfg != nil {
|
||||
current = cfg.DefaultAs
|
||||
}
|
||||
}
|
||||
if current == "" && app != nil {
|
||||
current = app.DefaultAs
|
||||
}
|
||||
if current == "" {
|
||||
current = "auto"
|
||||
}
|
||||
fmt.Fprintf(f.IOStreams.Out, "default-as: %s\n", current)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/larksuite/cli/internal/cmdutil"
|
||||
"github.com/larksuite/cli/internal/core"
|
||||
@@ -81,19 +81,30 @@ func showStrictMode(f *cmdutil.Factory, multi *core.MultiAppConfig, app *core.Ap
|
||||
// Runtime effective mode from credential provider chain is the source of truth.
|
||||
runtime := f.ResolveStrictMode()
|
||||
configMode, configSource := resolveStrictModeStatus(multi, app)
|
||||
if source := resolveRuntimeStrictModeSource(f); source != "" {
|
||||
fmt.Fprintf(f.IOStreams.Out, "strict-mode: %s (source: %s)\n", runtime, source)
|
||||
return nil
|
||||
}
|
||||
|
||||
if runtime != configMode {
|
||||
source := "credential provider"
|
||||
if os.Getenv("LARKSUITE_CLI_STRICT_MODE") != "" {
|
||||
source = "env LARKSUITE_CLI_STRICT_MODE"
|
||||
}
|
||||
fmt.Fprintf(f.IOStreams.Out, "strict-mode: %s (source: %s)\n", runtime, source)
|
||||
fmt.Fprintf(f.IOStreams.Out, "strict-mode: %s (source: credential provider)\n", runtime)
|
||||
return nil
|
||||
}
|
||||
fmt.Fprintf(f.IOStreams.Out, "strict-mode: %s (source: %s)\n", configMode, configSource)
|
||||
return nil
|
||||
}
|
||||
|
||||
func resolveRuntimeStrictModeSource(f *cmdutil.Factory) string {
|
||||
if f == nil || f.Credential == nil {
|
||||
return ""
|
||||
}
|
||||
name, err := f.Credential.ResolveSourceName(context.Background())
|
||||
if err != nil || name == "" || name == "default" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("credential provider %q", name)
|
||||
}
|
||||
|
||||
func setStrictMode(f *cmdutil.Factory, multi *core.MultiAppConfig, app *core.AppConfig, value string, global bool) error {
|
||||
mode := core.StrictMode(value)
|
||||
switch mode {
|
||||
|
||||
@@ -4,13 +4,29 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
extcred "github.com/larksuite/cli/extension/credential"
|
||||
"github.com/larksuite/cli/internal/cmdutil"
|
||||
"github.com/larksuite/cli/internal/core"
|
||||
"github.com/larksuite/cli/internal/credential"
|
||||
)
|
||||
|
||||
type stubStrictModeProvider struct {
|
||||
name string
|
||||
account *extcred.Account
|
||||
}
|
||||
|
||||
func (p *stubStrictModeProvider) Name() string { return p.name }
|
||||
func (p *stubStrictModeProvider) ResolveAccount(ctx context.Context) (*extcred.Account, error) {
|
||||
return p.account, nil
|
||||
}
|
||||
func (p *stubStrictModeProvider) ResolveToken(ctx context.Context, req extcred.TokenSpec) (*extcred.Token, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func setupStrictModeTestConfig(t *testing.T) {
|
||||
t.Helper()
|
||||
dir := t.TempDir()
|
||||
@@ -130,3 +146,44 @@ func TestStrictMode_InvalidValue(t *testing.T) {
|
||||
t.Error("expected error for invalid value 'on'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStrictMode_Show_PrefersExternalCredentialSourceEvenWhenValueMatchesConfig(t *testing.T) {
|
||||
setupStrictModeTestConfig(t)
|
||||
|
||||
multi, err := core.LoadMultiAppConfig()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mode := core.StrictModeBot
|
||||
multi.Apps[0].StrictMode = &mode
|
||||
if err := core.SaveMultiAppConfig(multi); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
f, stdout, _, _ := cmdutil.TestFactory(t, &core.CliConfig{AppID: "test-app", AppSecret: "secret"})
|
||||
f.Credential = credential.NewCredentialProvider(
|
||||
[]extcred.Provider{&stubStrictModeProvider{
|
||||
name: "env",
|
||||
account: &extcred.Account{
|
||||
AppID: "env-app",
|
||||
AppSecret: "env-secret",
|
||||
Brand: string(core.BrandFeishu),
|
||||
SupportedIdentities: extcred.SupportsBot,
|
||||
},
|
||||
}},
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
cmd := NewCmdConfigStrictMode(f)
|
||||
cmd.SetArgs([]string{})
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := `strict-mode: bot (source: credential provider "env")`
|
||||
if !strings.Contains(stdout.String(), want) {
|
||||
t.Fatalf("output = %q, want substring %q", stdout.String(), want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,6 +254,19 @@ func (p *CredentialProvider) selectedCredentialSource(ctx context.Context) (cred
|
||||
return p.selectedSource, nil
|
||||
}
|
||||
|
||||
func (p *CredentialProvider) ResolveSourceName(ctx context.Context) (string, error) {
|
||||
if p.selectedSource == nil {
|
||||
if _, err := p.ResolveAccount(ctx); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
source := p.selectedSource
|
||||
if source == nil {
|
||||
return "", nil
|
||||
}
|
||||
return source.Name(), nil
|
||||
}
|
||||
|
||||
func resolveTokenFromSource(ctx context.Context, source credentialSource, req TokenSpec) (*TokenResult, error) {
|
||||
result, found, err := source.TryResolveToken(ctx, req)
|
||||
if err != nil {
|
||||
|
||||
@@ -320,6 +320,26 @@ func TestCredentialProvider_ResolveTokenTreatsEmptyDefaultTokenAsMalformed(t *te
|
||||
}
|
||||
}
|
||||
|
||||
func TestCredentialProvider_ResolveSourceName_SelectedExtensionSource(t *testing.T) {
|
||||
cp := NewCredentialProvider(
|
||||
[]extcred.Provider{&mockExtProvider{
|
||||
name: "env",
|
||||
account: &extcred.Account{AppID: "ext_app", Brand: "feishu"},
|
||||
}},
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
name, err := cp.ResolveSourceName(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("ResolveSourceName() error = %v", err)
|
||||
}
|
||||
if name != "env" {
|
||||
t.Fatalf("ResolveSourceName() = %q, want %q", name, "env")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCredentialProvider_ResolveAccountDoesNotEnrichWithTokenFromDifferentProvider(t *testing.T) {
|
||||
httpClientCalls := 0
|
||||
cp := NewCredentialProvider(
|
||||
|
||||
Reference in New Issue
Block a user