mirror of
https://github.com/larksuite/cli.git
synced 2026-08-03 08:32:46 +08:00
refactor(extension): remove internal package dependencies
This commit is contained in:
@@ -14,11 +14,11 @@ import (
|
||||
"github.com/larksuite/cli/cmd/api"
|
||||
"github.com/larksuite/cli/cmd/auth"
|
||||
"github.com/larksuite/cli/cmd/service"
|
||||
"github.com/larksuite/cli/envnames"
|
||||
"github.com/larksuite/cli/internal/apicatalog"
|
||||
"github.com/larksuite/cli/internal/build"
|
||||
"github.com/larksuite/cli/internal/cmdutil"
|
||||
"github.com/larksuite/cli/internal/core"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
"github.com/larksuite/cli/internal/httpmock"
|
||||
"github.com/larksuite/cli/internal/meta"
|
||||
"github.com/larksuite/cli/internal/output"
|
||||
@@ -157,11 +157,11 @@ func strictModeFixtureCatalog() apicatalog.Catalog {
|
||||
|
||||
func newStrictModeDefaultFactory(t *testing.T, profile string, mode core.StrictMode) (*cmdutil.Factory, *bytes.Buffer, *bytes.Buffer) {
|
||||
t.Helper()
|
||||
t.Setenv(envvars.CliAppID, "")
|
||||
t.Setenv(envvars.CliAppSecret, "")
|
||||
t.Setenv(envvars.CliUserAccessToken, "")
|
||||
t.Setenv(envvars.CliTenantAccessToken, "")
|
||||
t.Setenv(envvars.CliDefaultAs, "")
|
||||
t.Setenv(envnames.CliAppID, "")
|
||||
t.Setenv(envnames.CliAppSecret, "")
|
||||
t.Setenv(envnames.CliUserAccessToken, "")
|
||||
t.Setenv(envnames.CliTenantAccessToken, "")
|
||||
t.Setenv(envnames.CliDefaultAs, "")
|
||||
|
||||
dir := t.TempDir()
|
||||
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", dir)
|
||||
|
||||
@@ -6,8 +6,8 @@ package cmd
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
"github.com/larksuite/cli/internal/core"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
)
|
||||
|
||||
// ResolveStartupBrand resolves the brand before the command tree is built, so
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
// environment, then the active profile's raw config entry — without touching
|
||||
// the keychain (no secrets are needed to know the brand).
|
||||
func ResolveStartupBrand(profile string) core.LarkBrand {
|
||||
if raw := os.Getenv(envvars.CliBrand); raw != "" {
|
||||
if raw := os.Getenv(envnames.CliBrand); raw != "" {
|
||||
return core.ParseBrand(raw)
|
||||
}
|
||||
if cfg, err := core.LoadMultiAppConfig(); err == nil {
|
||||
|
||||
18
envnames/envnames.go
Normal file
18
envnames/envnames.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Package envnames defines environment variable names shared by the CLI and
|
||||
// its public extension packages.
|
||||
package envnames
|
||||
|
||||
const (
|
||||
CliAppID = "LARKSUITE_CLI_APP_ID"
|
||||
CliAppSecret = "LARKSUITE_CLI_APP_SECRET"
|
||||
CliBrand = "LARKSUITE_CLI_BRAND"
|
||||
CliUserAccessToken = "LARKSUITE_CLI_USER_ACCESS_TOKEN"
|
||||
CliTenantAccessToken = "LARKSUITE_CLI_TENANT_ACCESS_TOKEN"
|
||||
CliDefaultAs = "LARKSUITE_CLI_DEFAULT_AS"
|
||||
CliStrictMode = "LARKSUITE_CLI_STRICT_MODE"
|
||||
CliAuthProxy = "LARKSUITE_CLI_AUTH_PROXY"
|
||||
CliProxyKey = "LARKSUITE_CLI_PROXY_KEY"
|
||||
)
|
||||
41
extension/credential/env/env.go
vendored
41
extension/credential/env/env.go
vendored
@@ -7,10 +7,10 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
"github.com/larksuite/cli/extension/credential"
|
||||
"github.com/larksuite/cli/internal/core"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
)
|
||||
|
||||
// Provider resolves credentials from environment variables.
|
||||
@@ -19,33 +19,33 @@ type Provider struct{}
|
||||
func (p *Provider) Name() string { return "env" }
|
||||
|
||||
func (p *Provider) ResolveAccount(ctx context.Context) (*credential.Account, error) {
|
||||
appID := os.Getenv(envvars.CliAppID)
|
||||
appSecret := os.Getenv(envvars.CliAppSecret)
|
||||
hasUAT := os.Getenv(envvars.CliUserAccessToken) != ""
|
||||
hasTAT := os.Getenv(envvars.CliTenantAccessToken) != ""
|
||||
appID := os.Getenv(envnames.CliAppID)
|
||||
appSecret := os.Getenv(envnames.CliAppSecret)
|
||||
hasUAT := os.Getenv(envnames.CliUserAccessToken) != ""
|
||||
hasTAT := os.Getenv(envnames.CliTenantAccessToken) != ""
|
||||
if appID == "" && appSecret == "" {
|
||||
switch {
|
||||
case hasUAT:
|
||||
return nil, &credential.BlockError{Provider: "env", Reason: envvars.CliUserAccessToken + " is set but " + envvars.CliAppID + " is missing"}
|
||||
return nil, &credential.BlockError{Provider: "env", Reason: envnames.CliUserAccessToken + " is set but " + envnames.CliAppID + " is missing"}
|
||||
case hasTAT:
|
||||
return nil, &credential.BlockError{Provider: "env", Reason: envvars.CliTenantAccessToken + " is set but " + envvars.CliAppID + " is missing"}
|
||||
return nil, &credential.BlockError{Provider: "env", Reason: envnames.CliTenantAccessToken + " is set but " + envnames.CliAppID + " is missing"}
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
if appID == "" {
|
||||
return nil, &credential.BlockError{Provider: "env", Reason: envvars.CliAppSecret + " is set but " + envvars.CliAppID + " is missing"}
|
||||
return nil, &credential.BlockError{Provider: "env", Reason: envnames.CliAppSecret + " is set but " + envnames.CliAppID + " is missing"}
|
||||
}
|
||||
if appSecret == "" && !hasUAT && !hasTAT {
|
||||
return nil, &credential.BlockError{
|
||||
Provider: "env",
|
||||
Reason: envvars.CliAppID + " is set but no app secret or access token is available",
|
||||
Reason: envnames.CliAppID + " is set but no app secret or access token is available",
|
||||
}
|
||||
}
|
||||
brand := credential.Brand(core.ParseBrand(os.Getenv(envvars.CliBrand)))
|
||||
brand := parseBrand(os.Getenv(envnames.CliBrand))
|
||||
acct := &credential.Account{AppID: appID, AppSecret: appSecret, Brand: brand}
|
||||
|
||||
switch id := credential.Identity(os.Getenv(envvars.CliDefaultAs)); id {
|
||||
switch id := credential.Identity(os.Getenv(envnames.CliDefaultAs)); id {
|
||||
case "", credential.IdentityAuto:
|
||||
acct.DefaultAs = id
|
||||
case credential.IdentityUser, credential.IdentityBot:
|
||||
@@ -53,12 +53,12 @@ func (p *Provider) ResolveAccount(ctx context.Context) (*credential.Account, err
|
||||
default:
|
||||
return nil, &credential.BlockError{
|
||||
Provider: "env",
|
||||
Reason: fmt.Sprintf("invalid %s %q (want user, bot, or auto)", envvars.CliDefaultAs, id),
|
||||
Reason: fmt.Sprintf("invalid %s %q (want user, bot, or auto)", envnames.CliDefaultAs, id),
|
||||
}
|
||||
}
|
||||
|
||||
// Explicit strict mode policy takes priority
|
||||
switch strictMode := os.Getenv(envvars.CliStrictMode); strictMode {
|
||||
switch strictMode := os.Getenv(envnames.CliStrictMode); strictMode {
|
||||
case "bot":
|
||||
acct.SupportedIdentities = credential.SupportsBot
|
||||
case "user":
|
||||
@@ -76,7 +76,7 @@ func (p *Provider) ResolveAccount(ctx context.Context) (*credential.Account, err
|
||||
default:
|
||||
return nil, &credential.BlockError{
|
||||
Provider: "env",
|
||||
Reason: fmt.Sprintf("invalid %s %q (want bot, user, or off)", envvars.CliStrictMode, strictMode),
|
||||
Reason: fmt.Sprintf("invalid %s %q (want bot, user, or off)", envnames.CliStrictMode, strictMode),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,9 +96,9 @@ func (p *Provider) ResolveToken(ctx context.Context, req credential.TokenSpec) (
|
||||
var envKey string
|
||||
switch req.Type {
|
||||
case credential.TokenTypeUAT:
|
||||
envKey = envvars.CliUserAccessToken
|
||||
envKey = envnames.CliUserAccessToken
|
||||
case credential.TokenTypeTAT:
|
||||
envKey = envvars.CliTenantAccessToken
|
||||
envKey = envnames.CliTenantAccessToken
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
@@ -109,6 +109,13 @@ func (p *Provider) ResolveToken(ctx context.Context, req credential.TokenSpec) (
|
||||
return &credential.Token{Value: token, Source: "env:" + envKey}, nil
|
||||
}
|
||||
|
||||
func parseBrand(value string) credential.Brand {
|
||||
if strings.ToLower(strings.TrimSpace(value)) == "lark" {
|
||||
return credential.BrandLark
|
||||
}
|
||||
return credential.BrandFeishu
|
||||
}
|
||||
|
||||
func init() {
|
||||
credential.Register(&Provider{})
|
||||
}
|
||||
|
||||
108
extension/credential/env/env_test.go
vendored
108
extension/credential/env/env_test.go
vendored
@@ -9,8 +9,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
"github.com/larksuite/cli/extension/credential"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
)
|
||||
|
||||
func TestProvider_Name(t *testing.T) {
|
||||
@@ -20,9 +20,9 @@ func TestProvider_Name(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_BothSet(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "cli_test")
|
||||
t.Setenv(envvars.CliAppSecret, "secret_test")
|
||||
t.Setenv(envvars.CliBrand, " LARK ")
|
||||
t.Setenv(envnames.CliAppID, "cli_test")
|
||||
t.Setenv(envnames.CliAppSecret, "secret_test")
|
||||
t.Setenv(envnames.CliBrand, " LARK ")
|
||||
|
||||
acct, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
if err != nil {
|
||||
@@ -41,7 +41,7 @@ func TestResolveAccount_NeitherSet(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_OnlyIDSet(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "cli_test")
|
||||
t.Setenv(envnames.CliAppID, "cli_test")
|
||||
_, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
var blockErr *credential.BlockError
|
||||
if !errors.As(err, &blockErr) {
|
||||
@@ -50,8 +50,8 @@ func TestResolveAccount_OnlyIDSet(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_AppIDAndUserTokenWithoutSecret(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "cli_test")
|
||||
t.Setenv(envvars.CliUserAccessToken, "uat_test")
|
||||
t.Setenv(envnames.CliAppID, "cli_test")
|
||||
t.Setenv(envnames.CliUserAccessToken, "uat_test")
|
||||
|
||||
acct, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
if err != nil {
|
||||
@@ -69,7 +69,7 @@ func TestResolveAccount_AppIDAndUserTokenWithoutSecret(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_OnlySecretSet(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppSecret, "secret_test")
|
||||
t.Setenv(envnames.CliAppSecret, "secret_test")
|
||||
_, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
var blockErr *credential.BlockError
|
||||
if !errors.As(err, &blockErr) {
|
||||
@@ -78,21 +78,21 @@ func TestResolveAccount_OnlySecretSet(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_OnlyTokenSetWithoutAppID(t *testing.T) {
|
||||
t.Setenv(envvars.CliUserAccessToken, "uat_test")
|
||||
t.Setenv(envnames.CliUserAccessToken, "uat_test")
|
||||
|
||||
_, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
var blockErr *credential.BlockError
|
||||
if !errors.As(err, &blockErr) {
|
||||
t.Fatalf("expected BlockError, got %v", err)
|
||||
}
|
||||
if !strings.Contains(err.Error(), envvars.CliAppID) {
|
||||
t.Fatalf("error = %v, want mention of %s", err, envvars.CliAppID)
|
||||
if !strings.Contains(err.Error(), envnames.CliAppID) {
|
||||
t.Fatalf("error = %v, want mention of %s", err, envnames.CliAppID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveAccount_DefaultBrand(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "cli_test")
|
||||
t.Setenv(envvars.CliAppSecret, "secret_test")
|
||||
t.Setenv(envnames.CliAppID, "cli_test")
|
||||
t.Setenv(envnames.CliAppSecret, "secret_test")
|
||||
acct, _ := (&Provider{}).ResolveAccount(context.Background())
|
||||
if acct.Brand != "feishu" {
|
||||
t.Errorf("expected 'feishu', got %q", acct.Brand)
|
||||
@@ -100,9 +100,9 @@ func TestResolveAccount_DefaultBrand(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_DefaultAsFromEnv(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "cli_test")
|
||||
t.Setenv(envvars.CliAppSecret, "secret_test")
|
||||
t.Setenv(envvars.CliDefaultAs, "user")
|
||||
t.Setenv(envnames.CliAppID, "cli_test")
|
||||
t.Setenv(envnames.CliAppSecret, "secret_test")
|
||||
t.Setenv(envnames.CliDefaultAs, "user")
|
||||
|
||||
acct, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
if err != nil {
|
||||
@@ -114,23 +114,23 @@ func TestResolveAccount_DefaultAsFromEnv(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveToken_UATSet(t *testing.T) {
|
||||
t.Setenv(envvars.CliUserAccessToken, "u-env")
|
||||
t.Setenv(envnames.CliUserAccessToken, "u-env")
|
||||
tok, err := (&Provider{}).ResolveToken(context.Background(), credential.TokenSpec{Type: credential.TokenTypeUAT})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if tok.Value != "u-env" || tok.Source != "env:"+envvars.CliUserAccessToken {
|
||||
if tok.Value != "u-env" || tok.Source != "env:"+envnames.CliUserAccessToken {
|
||||
t.Errorf("unexpected: %+v", tok)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveToken_TATSet(t *testing.T) {
|
||||
t.Setenv(envvars.CliTenantAccessToken, "t-env")
|
||||
t.Setenv(envnames.CliTenantAccessToken, "t-env")
|
||||
tok, err := (&Provider{}).ResolveToken(context.Background(), credential.TokenSpec{Type: credential.TokenTypeTAT})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if tok.Value != "t-env" || tok.Source != "env:"+envvars.CliTenantAccessToken {
|
||||
if tok.Value != "t-env" || tok.Source != "env:"+envnames.CliTenantAccessToken {
|
||||
t.Errorf("unexpected: %+v", tok)
|
||||
}
|
||||
}
|
||||
@@ -143,9 +143,9 @@ func TestResolveToken_NotSet(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_StrictModeBot(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "app")
|
||||
t.Setenv(envvars.CliAppSecret, "secret")
|
||||
t.Setenv(envvars.CliStrictMode, "bot")
|
||||
t.Setenv(envnames.CliAppID, "app")
|
||||
t.Setenv(envnames.CliAppSecret, "secret")
|
||||
t.Setenv(envnames.CliStrictMode, "bot")
|
||||
acct, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -156,9 +156,9 @@ func TestResolveAccount_StrictModeBot(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_StrictModeUser(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "app")
|
||||
t.Setenv(envvars.CliAppSecret, "secret")
|
||||
t.Setenv(envvars.CliStrictMode, "user")
|
||||
t.Setenv(envnames.CliAppID, "app")
|
||||
t.Setenv(envnames.CliAppSecret, "secret")
|
||||
t.Setenv(envnames.CliStrictMode, "user")
|
||||
acct, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -169,9 +169,9 @@ func TestResolveAccount_StrictModeUser(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_StrictModeOff(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "app")
|
||||
t.Setenv(envvars.CliAppSecret, "secret")
|
||||
t.Setenv(envvars.CliStrictMode, "off")
|
||||
t.Setenv(envnames.CliAppID, "app")
|
||||
t.Setenv(envnames.CliAppSecret, "secret")
|
||||
t.Setenv(envnames.CliStrictMode, "off")
|
||||
acct, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -182,9 +182,9 @@ func TestResolveAccount_StrictModeOff(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_InferFromUATOnly(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "app")
|
||||
t.Setenv(envvars.CliAppSecret, "secret")
|
||||
t.Setenv(envvars.CliUserAccessToken, "u-tok")
|
||||
t.Setenv(envnames.CliAppID, "app")
|
||||
t.Setenv(envnames.CliAppSecret, "secret")
|
||||
t.Setenv(envnames.CliUserAccessToken, "u-tok")
|
||||
acct, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -198,9 +198,9 @@ func TestResolveAccount_InferFromUATOnly(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_InferFromTATOnly(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "app")
|
||||
t.Setenv(envvars.CliAppSecret, "secret")
|
||||
t.Setenv(envvars.CliTenantAccessToken, "t-tok")
|
||||
t.Setenv(envnames.CliAppID, "app")
|
||||
t.Setenv(envnames.CliAppSecret, "secret")
|
||||
t.Setenv(envnames.CliTenantAccessToken, "t-tok")
|
||||
acct, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -214,10 +214,10 @@ func TestResolveAccount_InferFromTATOnly(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_InferBothTokens(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "app")
|
||||
t.Setenv(envvars.CliAppSecret, "secret")
|
||||
t.Setenv(envvars.CliUserAccessToken, "u-tok")
|
||||
t.Setenv(envvars.CliTenantAccessToken, "t-tok")
|
||||
t.Setenv(envnames.CliAppID, "app")
|
||||
t.Setenv(envnames.CliAppSecret, "secret")
|
||||
t.Setenv(envnames.CliUserAccessToken, "u-tok")
|
||||
t.Setenv(envnames.CliTenantAccessToken, "t-tok")
|
||||
acct, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -231,11 +231,11 @@ func TestResolveAccount_InferBothTokens(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_StrictModeOverridesTokenInference(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "app")
|
||||
t.Setenv(envvars.CliAppSecret, "secret")
|
||||
t.Setenv(envvars.CliUserAccessToken, "u-tok")
|
||||
t.Setenv(envvars.CliTenantAccessToken, "t-tok")
|
||||
t.Setenv(envvars.CliStrictMode, "bot")
|
||||
t.Setenv(envnames.CliAppID, "app")
|
||||
t.Setenv(envnames.CliAppSecret, "secret")
|
||||
t.Setenv(envnames.CliUserAccessToken, "u-tok")
|
||||
t.Setenv(envnames.CliTenantAccessToken, "t-tok")
|
||||
t.Setenv(envnames.CliStrictMode, "bot")
|
||||
acct, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -246,9 +246,9 @@ func TestResolveAccount_StrictModeOverridesTokenInference(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_InvalidStrictModeRejected(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "app")
|
||||
t.Setenv(envvars.CliAppSecret, "secret")
|
||||
t.Setenv(envvars.CliStrictMode, "invalid")
|
||||
t.Setenv(envnames.CliAppID, "app")
|
||||
t.Setenv(envnames.CliAppSecret, "secret")
|
||||
t.Setenv(envnames.CliStrictMode, "invalid")
|
||||
|
||||
_, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
if err == nil {
|
||||
@@ -258,15 +258,15 @@ func TestResolveAccount_InvalidStrictModeRejected(t *testing.T) {
|
||||
if !errors.As(err, &blockErr) {
|
||||
t.Fatalf("expected BlockError, got %T", err)
|
||||
}
|
||||
if !strings.Contains(err.Error(), envvars.CliStrictMode) {
|
||||
t.Fatalf("error = %v, want mention of %s", err, envvars.CliStrictMode)
|
||||
if !strings.Contains(err.Error(), envnames.CliStrictMode) {
|
||||
t.Fatalf("error = %v, want mention of %s", err, envnames.CliStrictMode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveAccount_InvalidDefaultAsRejected(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "app")
|
||||
t.Setenv(envvars.CliAppSecret, "secret")
|
||||
t.Setenv(envvars.CliDefaultAs, "invalid")
|
||||
t.Setenv(envnames.CliAppID, "app")
|
||||
t.Setenv(envnames.CliAppSecret, "secret")
|
||||
t.Setenv(envnames.CliDefaultAs, "invalid")
|
||||
|
||||
_, err := (&Provider{}).ResolveAccount(context.Background())
|
||||
if err == nil {
|
||||
@@ -276,7 +276,7 @@ func TestResolveAccount_InvalidDefaultAsRejected(t *testing.T) {
|
||||
if !errors.As(err, &blockErr) {
|
||||
t.Fatalf("expected BlockError, got %T", err)
|
||||
}
|
||||
if !strings.Contains(err.Error(), envvars.CliDefaultAs) {
|
||||
t.Fatalf("error = %v, want mention of %s", err, envvars.CliDefaultAs)
|
||||
if !strings.Contains(err.Error(), envnames.CliDefaultAs) {
|
||||
t.Fatalf("error = %v, want mention of %s", err, envnames.CliDefaultAs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
"github.com/larksuite/cli/extension/credential"
|
||||
"github.com/larksuite/cli/internal/core"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
"github.com/larksuite/cli/sidecar"
|
||||
)
|
||||
|
||||
@@ -32,7 +32,7 @@ func (p *Provider) Priority() int { return 0 }
|
||||
// placeholder secret, and SupportedIdentities derived from STRICT_MODE.
|
||||
// Returns nil, nil when sidecar mode is not active (AUTH_PROXY not set).
|
||||
func (p *Provider) ResolveAccount(ctx context.Context) (*credential.Account, error) {
|
||||
proxyAddr := os.Getenv(envvars.CliAuthProxy)
|
||||
proxyAddr := os.Getenv(envnames.CliAuthProxy)
|
||||
if proxyAddr == "" {
|
||||
return nil, nil // not in sidecar mode, skip
|
||||
}
|
||||
@@ -40,26 +40,26 @@ func (p *Provider) ResolveAccount(ctx context.Context) (*credential.Account, err
|
||||
if err := sidecar.ValidateProxyAddr(proxyAddr); err != nil {
|
||||
return nil, &credential.BlockError{
|
||||
Provider: "sidecar",
|
||||
Reason: fmt.Sprintf("invalid %s %q: %v", envvars.CliAuthProxy, proxyAddr, err),
|
||||
Reason: fmt.Sprintf("invalid %s %q: %v", envnames.CliAuthProxy, proxyAddr, err),
|
||||
}
|
||||
}
|
||||
|
||||
appID := os.Getenv(envvars.CliAppID)
|
||||
appID := os.Getenv(envnames.CliAppID)
|
||||
if appID == "" {
|
||||
return nil, &credential.BlockError{
|
||||
Provider: "sidecar",
|
||||
Reason: envvars.CliAuthProxy + " is set but " + envvars.CliAppID + " is missing",
|
||||
Reason: envnames.CliAuthProxy + " is set but " + envnames.CliAppID + " is missing",
|
||||
}
|
||||
}
|
||||
|
||||
if os.Getenv(envvars.CliProxyKey) == "" {
|
||||
if os.Getenv(envnames.CliProxyKey) == "" {
|
||||
return nil, &credential.BlockError{
|
||||
Provider: "sidecar",
|
||||
Reason: envvars.CliAuthProxy + " is set but " + envvars.CliProxyKey + " is missing",
|
||||
Reason: envnames.CliAuthProxy + " is set but " + envnames.CliProxyKey + " is missing",
|
||||
}
|
||||
}
|
||||
|
||||
brand := credential.Brand(core.ParseBrand(os.Getenv(envvars.CliBrand)))
|
||||
brand := parseBrand(os.Getenv(envnames.CliBrand))
|
||||
|
||||
acct := &credential.Account{
|
||||
AppID: appID,
|
||||
@@ -68,7 +68,7 @@ func (p *Provider) ResolveAccount(ctx context.Context) (*credential.Account, err
|
||||
}
|
||||
|
||||
// Parse DefaultAs
|
||||
switch id := credential.Identity(os.Getenv(envvars.CliDefaultAs)); id {
|
||||
switch id := credential.Identity(os.Getenv(envnames.CliDefaultAs)); id {
|
||||
case "", credential.IdentityAuto:
|
||||
acct.DefaultAs = id
|
||||
case credential.IdentityUser, credential.IdentityBot:
|
||||
@@ -76,12 +76,12 @@ func (p *Provider) ResolveAccount(ctx context.Context) (*credential.Account, err
|
||||
default:
|
||||
return nil, &credential.BlockError{
|
||||
Provider: "sidecar",
|
||||
Reason: fmt.Sprintf("invalid %s %q (want user, bot, or auto)", envvars.CliDefaultAs, id),
|
||||
Reason: fmt.Sprintf("invalid %s %q (want user, bot, or auto)", envnames.CliDefaultAs, id),
|
||||
}
|
||||
}
|
||||
|
||||
// Parse SupportedIdentities from STRICT_MODE, default to SupportsAll.
|
||||
switch strictMode := os.Getenv(envvars.CliStrictMode); strictMode {
|
||||
switch strictMode := os.Getenv(envnames.CliStrictMode); strictMode {
|
||||
case "bot":
|
||||
acct.SupportedIdentities = credential.SupportsBot
|
||||
case "user":
|
||||
@@ -91,7 +91,7 @@ func (p *Provider) ResolveAccount(ctx context.Context) (*credential.Account, err
|
||||
default:
|
||||
return nil, &credential.BlockError{
|
||||
Provider: "sidecar",
|
||||
Reason: fmt.Sprintf("invalid %s %q (want bot, user, or off)", envvars.CliStrictMode, strictMode),
|
||||
Reason: fmt.Sprintf("invalid %s %q (want bot, user, or off)", envnames.CliStrictMode, strictMode),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ func (p *Provider) ResolveAccount(ctx context.Context) (*credential.Account, err
|
||||
// (user vs bot), strips it, and the sidecar injects the real token.
|
||||
// Returns nil, nil when sidecar mode is not active.
|
||||
func (p *Provider) ResolveToken(ctx context.Context, req credential.TokenSpec) (*credential.Token, error) {
|
||||
if os.Getenv(envvars.CliAuthProxy) == "" {
|
||||
if os.Getenv(envnames.CliAuthProxy) == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -124,6 +124,13 @@ func (p *Provider) ResolveToken(ctx context.Context, req credential.TokenSpec) (
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseBrand(value string) credential.Brand {
|
||||
if strings.ToLower(strings.TrimSpace(value)) == "lark" {
|
||||
return credential.BrandLark
|
||||
}
|
||||
return credential.BrandFeishu
|
||||
}
|
||||
|
||||
func init() {
|
||||
credential.Register(&Provider{})
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
"github.com/larksuite/cli/extension/credential"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
"github.com/larksuite/cli/sidecar"
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ func unsetEnv(t *testing.T, key string) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_NotActive(t *testing.T) {
|
||||
unsetEnv(t, envvars.CliAuthProxy)
|
||||
unsetEnv(t, envnames.CliAuthProxy)
|
||||
|
||||
p := &Provider{}
|
||||
acct, err := p.ResolveAccount(context.Background())
|
||||
@@ -53,12 +53,12 @@ func TestResolveAccount_NotActive(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_Active(t *testing.T) {
|
||||
setEnv(t, envvars.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
setEnv(t, envvars.CliProxyKey, "test-key")
|
||||
setEnv(t, envvars.CliAppID, "cli_test123")
|
||||
setEnv(t, envvars.CliBrand, " LARK ")
|
||||
unsetEnv(t, envvars.CliDefaultAs)
|
||||
unsetEnv(t, envvars.CliStrictMode)
|
||||
setEnv(t, envnames.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
setEnv(t, envnames.CliProxyKey, "test-key")
|
||||
setEnv(t, envnames.CliAppID, "cli_test123")
|
||||
setEnv(t, envnames.CliBrand, " LARK ")
|
||||
unsetEnv(t, envnames.CliDefaultAs)
|
||||
unsetEnv(t, envnames.CliStrictMode)
|
||||
|
||||
p := &Provider{}
|
||||
acct, err := p.ResolveAccount(context.Background())
|
||||
@@ -83,9 +83,9 @@ func TestResolveAccount_Active(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_MissingProxyKey(t *testing.T) {
|
||||
setEnv(t, envvars.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
unsetEnv(t, envvars.CliProxyKey)
|
||||
setEnv(t, envvars.CliAppID, "cli_test")
|
||||
setEnv(t, envnames.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
unsetEnv(t, envnames.CliProxyKey)
|
||||
setEnv(t, envnames.CliAppID, "cli_test")
|
||||
|
||||
p := &Provider{}
|
||||
_, err := p.ResolveAccount(context.Background())
|
||||
@@ -98,9 +98,9 @@ func TestResolveAccount_MissingProxyKey(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_MissingAppID(t *testing.T) {
|
||||
setEnv(t, envvars.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
setEnv(t, envvars.CliProxyKey, "test-key")
|
||||
unsetEnv(t, envvars.CliAppID)
|
||||
setEnv(t, envnames.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
setEnv(t, envnames.CliProxyKey, "test-key")
|
||||
unsetEnv(t, envnames.CliAppID)
|
||||
|
||||
p := &Provider{}
|
||||
_, err := p.ResolveAccount(context.Background())
|
||||
@@ -113,9 +113,9 @@ func TestResolveAccount_MissingAppID(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAccount_StrictMode(t *testing.T) {
|
||||
setEnv(t, envvars.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
setEnv(t, envvars.CliProxyKey, "test-key")
|
||||
setEnv(t, envvars.CliAppID, "cli_test")
|
||||
setEnv(t, envnames.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
setEnv(t, envnames.CliProxyKey, "test-key")
|
||||
setEnv(t, envnames.CliAppID, "cli_test")
|
||||
|
||||
tests := []struct {
|
||||
mode string
|
||||
@@ -131,9 +131,9 @@ func TestResolveAccount_StrictMode(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run("strict_"+tt.mode, func(t *testing.T) {
|
||||
if tt.mode == "" {
|
||||
unsetEnv(t, envvars.CliStrictMode)
|
||||
unsetEnv(t, envnames.CliStrictMode)
|
||||
} else {
|
||||
setEnv(t, envvars.CliStrictMode, tt.mode)
|
||||
setEnv(t, envnames.CliStrictMode, tt.mode)
|
||||
}
|
||||
acct, err := p.ResolveAccount(context.Background())
|
||||
if err != nil {
|
||||
@@ -147,7 +147,7 @@ func TestResolveAccount_StrictMode(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveToken_NotActive(t *testing.T) {
|
||||
unsetEnv(t, envvars.CliAuthProxy)
|
||||
unsetEnv(t, envnames.CliAuthProxy)
|
||||
|
||||
p := &Provider{}
|
||||
tok, err := p.ResolveToken(context.Background(), credential.TokenSpec{Type: credential.TokenTypeUAT})
|
||||
@@ -160,8 +160,8 @@ func TestResolveToken_NotActive(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveToken_Sentinels(t *testing.T) {
|
||||
setEnv(t, envvars.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
setEnv(t, envvars.CliProxyKey, "test-key")
|
||||
setEnv(t, envnames.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
setEnv(t, envnames.CliProxyKey, "test-key")
|
||||
|
||||
p := &Provider{}
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
"github.com/larksuite/cli/extension/transport"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
"github.com/larksuite/cli/sidecar"
|
||||
)
|
||||
|
||||
@@ -36,15 +36,15 @@ func (p *Provider) Name() string { return "sidecar" }
|
||||
// the non-sidecar transport path (where the credential layer will typically
|
||||
// block them for lack of a valid account).
|
||||
func (p *Provider) ResolveInterceptor(ctx context.Context) transport.Interceptor {
|
||||
proxyAddr := os.Getenv(envvars.CliAuthProxy)
|
||||
proxyAddr := os.Getenv(envnames.CliAuthProxy)
|
||||
if proxyAddr == "" {
|
||||
return nil
|
||||
}
|
||||
if err := sidecar.ValidateProxyAddr(proxyAddr); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "WARNING: invalid %s, sidecar interceptor disabled: %v\n", envvars.CliAuthProxy, err)
|
||||
fmt.Fprintf(os.Stderr, "WARNING: invalid %s, sidecar interceptor disabled: %v\n", envnames.CliAuthProxy, err)
|
||||
return nil
|
||||
}
|
||||
key := os.Getenv(envvars.CliProxyKey)
|
||||
key := os.Getenv(envnames.CliProxyKey)
|
||||
return &Interceptor{
|
||||
key: []byte(key),
|
||||
sidecarHost: sidecar.ProxyHost(proxyAddr),
|
||||
@@ -166,12 +166,12 @@ func detectSentinel(req *http.Request) (identity, authHeader string) {
|
||||
}
|
||||
|
||||
func init() {
|
||||
proxyAddr := os.Getenv(envvars.CliAuthProxy)
|
||||
proxyAddr := os.Getenv(envnames.CliAuthProxy)
|
||||
if proxyAddr == "" {
|
||||
return
|
||||
}
|
||||
if err := sidecar.ValidateProxyAddr(proxyAddr); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "WARNING: ignoring invalid %s: %v\n", envvars.CliAuthProxy, err)
|
||||
fmt.Fprintf(os.Stderr, "WARNING: ignoring invalid %s: %v\n", envnames.CliAuthProxy, err)
|
||||
return
|
||||
}
|
||||
transport.Register(&Provider{})
|
||||
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
"github.com/larksuite/cli/errs"
|
||||
_ "github.com/larksuite/cli/extension/credential/env"
|
||||
"github.com/larksuite/cli/extension/fileio"
|
||||
"github.com/larksuite/cli/internal/core"
|
||||
"github.com/larksuite/cli/internal/credential"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
"github.com/larksuite/cli/internal/vfs/localfileio"
|
||||
)
|
||||
|
||||
@@ -29,10 +29,10 @@ func (p *countingFileIOProvider) ResolveFileIO(context.Context) fileio.FileIO {
|
||||
}
|
||||
|
||||
func TestNewDefault_InvocationProfileUsedByStrictModeAndConfig(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "")
|
||||
t.Setenv(envvars.CliAppSecret, "")
|
||||
t.Setenv(envvars.CliUserAccessToken, "")
|
||||
t.Setenv(envvars.CliTenantAccessToken, "")
|
||||
t.Setenv(envnames.CliAppID, "")
|
||||
t.Setenv(envnames.CliAppSecret, "")
|
||||
t.Setenv(envnames.CliUserAccessToken, "")
|
||||
t.Setenv(envnames.CliTenantAccessToken, "")
|
||||
|
||||
dir := t.TempDir()
|
||||
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", dir)
|
||||
@@ -77,10 +77,10 @@ func TestNewDefault_InvocationProfileUsedByStrictModeAndConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewDefault_InvocationProfileMissingSticksAcrossEarlyStrictMode(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "")
|
||||
t.Setenv(envvars.CliAppSecret, "")
|
||||
t.Setenv(envvars.CliUserAccessToken, "")
|
||||
t.Setenv(envvars.CliTenantAccessToken, "")
|
||||
t.Setenv(envnames.CliAppID, "")
|
||||
t.Setenv(envnames.CliAppSecret, "")
|
||||
t.Setenv(envnames.CliUserAccessToken, "")
|
||||
t.Setenv(envnames.CliTenantAccessToken, "")
|
||||
|
||||
dir := t.TempDir()
|
||||
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", dir)
|
||||
@@ -118,11 +118,11 @@ func TestNewDefault_InvocationProfileMissingSticksAcrossEarlyStrictMode(t *testi
|
||||
}
|
||||
|
||||
func TestNewDefault_ResolveAs_UsesDefaultAsFromEnvAccount(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "env-app")
|
||||
t.Setenv(envvars.CliAppSecret, "env-secret")
|
||||
t.Setenv(envvars.CliDefaultAs, "user")
|
||||
t.Setenv(envvars.CliUserAccessToken, "")
|
||||
t.Setenv(envvars.CliTenantAccessToken, "")
|
||||
t.Setenv(envnames.CliAppID, "env-app")
|
||||
t.Setenv(envnames.CliAppSecret, "env-secret")
|
||||
t.Setenv(envnames.CliDefaultAs, "user")
|
||||
t.Setenv(envnames.CliUserAccessToken, "")
|
||||
t.Setenv(envnames.CliTenantAccessToken, "")
|
||||
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
|
||||
|
||||
f := NewDefault(nil, InvocationContext{})
|
||||
@@ -138,11 +138,11 @@ func TestNewDefault_ResolveAs_UsesDefaultAsFromEnvAccount(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewDefault_ConfigReturnsCliConfigCopyOfCredentialAccount(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "env-app")
|
||||
t.Setenv(envvars.CliAppSecret, "env-secret")
|
||||
t.Setenv(envvars.CliDefaultAs, "")
|
||||
t.Setenv(envvars.CliUserAccessToken, "uat-token")
|
||||
t.Setenv(envvars.CliTenantAccessToken, "")
|
||||
t.Setenv(envnames.CliAppID, "env-app")
|
||||
t.Setenv(envnames.CliAppSecret, "env-secret")
|
||||
t.Setenv(envnames.CliDefaultAs, "")
|
||||
t.Setenv(envnames.CliUserAccessToken, "uat-token")
|
||||
t.Setenv(envnames.CliTenantAccessToken, "")
|
||||
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
|
||||
|
||||
f := NewDefault(nil, InvocationContext{})
|
||||
@@ -163,11 +163,11 @@ func TestNewDefault_ConfigReturnsCliConfigCopyOfCredentialAccount(t *testing.T)
|
||||
}
|
||||
|
||||
func TestNewDefault_ConfigUsesRuntimePlaceholderForTokenOnlyEnvAccount(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "env-app")
|
||||
t.Setenv(envvars.CliAppSecret, "")
|
||||
t.Setenv(envvars.CliDefaultAs, "")
|
||||
t.Setenv(envvars.CliUserAccessToken, "uat-token")
|
||||
t.Setenv(envvars.CliTenantAccessToken, "")
|
||||
t.Setenv(envnames.CliAppID, "env-app")
|
||||
t.Setenv(envnames.CliAppSecret, "")
|
||||
t.Setenv(envnames.CliDefaultAs, "")
|
||||
t.Setenv(envnames.CliUserAccessToken, "uat-token")
|
||||
t.Setenv(envnames.CliTenantAccessToken, "")
|
||||
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
|
||||
|
||||
f := NewDefault(nil, InvocationContext{})
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
_ "github.com/larksuite/cli/extension/credential/env" // registers the env-backed account provider
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
)
|
||||
|
||||
// installProxyWarnSpy replaces warnIfProxied with a counter for one test and
|
||||
@@ -61,11 +61,11 @@ func TestCachedHttpClientFunc_ProxyWarnGate(t *testing.T) {
|
||||
func TestCachedLarkClientFunc_ProxyWarnGate(t *testing.T) {
|
||||
for _, tc := range proxyWarnGateCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "env-app")
|
||||
t.Setenv(envvars.CliAppSecret, "env-secret")
|
||||
t.Setenv(envvars.CliDefaultAs, "")
|
||||
t.Setenv(envvars.CliUserAccessToken, "")
|
||||
t.Setenv(envvars.CliTenantAccessToken, "")
|
||||
t.Setenv(envnames.CliAppID, "env-app")
|
||||
t.Setenv(envnames.CliAppSecret, "env-secret")
|
||||
t.Setenv(envnames.CliDefaultAs, "")
|
||||
t.Setenv(envnames.CliUserAccessToken, "")
|
||||
t.Setenv(envnames.CliTenantAccessToken, "")
|
||||
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
|
||||
|
||||
calls := installProxyWarnSpy(t)
|
||||
|
||||
@@ -11,11 +11,11 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
"github.com/larksuite/cli/errs"
|
||||
extcred "github.com/larksuite/cli/extension/credential"
|
||||
"github.com/larksuite/cli/internal/core"
|
||||
"github.com/larksuite/cli/internal/credential"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
"github.com/larksuite/cli/internal/output"
|
||||
)
|
||||
|
||||
@@ -92,7 +92,7 @@ func TestResolveAs_DefaultAs_FromConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveAs_DefaultAs_EnvDoesNotBypassConfigSource(t *testing.T) {
|
||||
t.Setenv(envvars.CliDefaultAs, "user")
|
||||
t.Setenv(envnames.CliDefaultAs, "user")
|
||||
|
||||
f, _, _, _ := TestFactory(t, &core.CliConfig{AppID: "a", AppSecret: "s"})
|
||||
cmd := newCmdWithAsFlag("auto", false)
|
||||
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
extcred "github.com/larksuite/cli/extension/credential"
|
||||
envprovider "github.com/larksuite/cli/extension/credential/env"
|
||||
"github.com/larksuite/cli/internal/core"
|
||||
"github.com/larksuite/cli/internal/credential"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
"github.com/larksuite/cli/internal/i18n"
|
||||
"github.com/larksuite/cli/internal/keychain"
|
||||
)
|
||||
@@ -23,9 +23,9 @@ func (n *noopKC) Set(service, account, value string) error { return nil }
|
||||
func (n *noopKC) Remove(service, account string) error { return nil }
|
||||
|
||||
func TestFullChain_EnvWins(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "env_app")
|
||||
t.Setenv(envvars.CliAppSecret, "env_secret")
|
||||
t.Setenv(envvars.CliUserAccessToken, "env_uat")
|
||||
t.Setenv(envnames.CliAppID, "env_app")
|
||||
t.Setenv(envnames.CliAppSecret, "env_secret")
|
||||
t.Setenv(envnames.CliUserAccessToken, "env_uat")
|
||||
|
||||
ep := &envprovider.Provider{}
|
||||
cp := credential.NewCredentialProvider(
|
||||
@@ -82,8 +82,8 @@ func (m *mockDefaultTokenProvider) ResolveToken(ctx context.Context, req credent
|
||||
}
|
||||
|
||||
func TestFullChain_ConfigStrictMode(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "")
|
||||
t.Setenv(envvars.CliAppSecret, "")
|
||||
t.Setenv(envnames.CliAppID, "")
|
||||
t.Setenv(envnames.CliAppSecret, "")
|
||||
dir := t.TempDir()
|
||||
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", dir)
|
||||
|
||||
@@ -125,8 +125,8 @@ func TestFullChain_ConfigStrictMode(t *testing.T) {
|
||||
// consumers (mail signature, etc.) silently fall back to defaults — defeating
|
||||
// the whole point of persisting --lang.
|
||||
func TestFullChain_LangSurvivesProductionPath(t *testing.T) {
|
||||
t.Setenv(envvars.CliAppID, "")
|
||||
t.Setenv(envvars.CliAppSecret, "")
|
||||
t.Setenv(envnames.CliAppID, "")
|
||||
t.Setenv(envnames.CliAppSecret, "")
|
||||
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
|
||||
|
||||
multi := &core.MultiAppConfig{
|
||||
|
||||
@@ -4,22 +4,9 @@
|
||||
package envvars
|
||||
|
||||
const (
|
||||
CliAppID = "LARKSUITE_CLI_APP_ID"
|
||||
CliAppSecret = "LARKSUITE_CLI_APP_SECRET"
|
||||
CliBrand = "LARKSUITE_CLI_BRAND"
|
||||
CliUserAccessToken = "LARKSUITE_CLI_USER_ACCESS_TOKEN"
|
||||
CliTenantAccessToken = "LARKSUITE_CLI_TENANT_ACCESS_TOKEN"
|
||||
CliDefaultAs = "LARKSUITE_CLI_DEFAULT_AS"
|
||||
CliStrictMode = "LARKSUITE_CLI_STRICT_MODE"
|
||||
|
||||
// Sidecar proxy (auth proxy mode)
|
||||
CliAuthProxy = "LARKSUITE_CLI_AUTH_PROXY" // sidecar HTTP address, e.g. "http://127.0.0.1:16384"
|
||||
CliProxyKey = "LARKSUITE_CLI_PROXY_KEY" // HMAC signing key shared with sidecar
|
||||
|
||||
// Content safety scanning mode
|
||||
CliContentSafetyMode = "LARKSUITE_CLI_CONTENT_SAFETY_MODE"
|
||||
|
||||
CliAgentName = "LARKSUITE_CLI_AGENT_NAME"
|
||||
CliAgentTrace = "LARKSUITE_CLI_AGENT_TRACE"
|
||||
|
||||
CliProxyEnable = "LARKSUITE_CLI_PROXY_ENABLE"
|
||||
|
||||
@@ -10,12 +10,13 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
agentNameEnv = "LARKSUITE_CLI_AGENT_NAME"
|
||||
agentNameMaxLen = 128
|
||||
agentTraceMaxLen = 1024
|
||||
)
|
||||
|
||||
func AgentName() string {
|
||||
return sanitizeSingleLine(os.Getenv(CliAgentName), agentNameMaxLen)
|
||||
return sanitizeSingleLine(os.Getenv(agentNameEnv), agentNameMaxLen)
|
||||
}
|
||||
|
||||
func AgentTrace() string {
|
||||
|
||||
@@ -9,35 +9,35 @@ import (
|
||||
)
|
||||
|
||||
func TestAgentName_EmptyWhenEnvUnset(t *testing.T) {
|
||||
t.Setenv(CliAgentName, "")
|
||||
t.Setenv(agentNameEnv, "")
|
||||
if got := AgentName(); got != "" {
|
||||
t.Fatalf("AgentName() = %q, want empty when env unset", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgentName_ReturnsCleanValue(t *testing.T) {
|
||||
t.Setenv(CliAgentName, "claude-code")
|
||||
t.Setenv(agentNameEnv, "claude-code")
|
||||
if got := AgentName(); got != "claude-code" {
|
||||
t.Fatalf("AgentName() = %q, want %q", got, "claude-code")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgentName_TrimsWhitespace(t *testing.T) {
|
||||
t.Setenv(CliAgentName, " cursor ")
|
||||
t.Setenv(agentNameEnv, " cursor ")
|
||||
if got := AgentName(); got != "cursor" {
|
||||
t.Fatalf("AgentName() = %q, want %q (whitespace trimmed)", got, "cursor")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgentName_RejectsCRLFInjection(t *testing.T) {
|
||||
t.Setenv(CliAgentName, "agent\r\nX-Evil: attack")
|
||||
t.Setenv(agentNameEnv, "agent\r\nX-Evil: attack")
|
||||
if got := AgentName(); got != "" {
|
||||
t.Fatalf("AgentName() = %q, want empty for CR/LF value", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgentName_RejectsControlChar(t *testing.T) {
|
||||
t.Setenv(CliAgentName, "agent\x01injected")
|
||||
t.Setenv(agentNameEnv, "agent\x01injected")
|
||||
if got := AgentName(); got != "" {
|
||||
t.Fatalf("AgentName() = %q, want empty for control char value", got)
|
||||
}
|
||||
@@ -45,7 +45,7 @@ func TestAgentName_RejectsControlChar(t *testing.T) {
|
||||
|
||||
func TestAgentName_RejectsOverlongValue(t *testing.T) {
|
||||
longVal := strings.Repeat("a", agentNameMaxLen+1)
|
||||
t.Setenv(CliAgentName, longVal)
|
||||
t.Setenv(agentNameEnv, longVal)
|
||||
if got := AgentName(); got != "" {
|
||||
t.Fatalf("AgentName() returned non-empty for %d-byte value (max %d)", len(longVal), agentNameMaxLen)
|
||||
}
|
||||
|
||||
@@ -1,21 +1,4 @@
|
||||
# from denied owner reason added_at
|
||||
github.com/larksuite/cli/extension/credential/env github.com/larksuite/cli/internal/charcheck arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/env github.com/larksuite/cli/internal/core arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/env github.com/larksuite/cli/internal/envvars arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/env github.com/larksuite/cli/internal/i18n arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/env github.com/larksuite/cli/internal/keychain arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/env github.com/larksuite/cli/internal/validate arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/env github.com/larksuite/cli/internal/vfs arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/env github.com/larksuite/cli/internal/vfs/localfileio arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/sidecar github.com/larksuite/cli/internal/charcheck arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/sidecar github.com/larksuite/cli/internal/core arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/sidecar github.com/larksuite/cli/internal/envvars arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/sidecar github.com/larksuite/cli/internal/i18n arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/sidecar github.com/larksuite/cli/internal/keychain arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/sidecar github.com/larksuite/cli/internal/validate arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/sidecar github.com/larksuite/cli/internal/vfs arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/credential/sidecar github.com/larksuite/cli/internal/vfs/localfileio arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/extension/transport/sidecar github.com/larksuite/cli/internal/envvars arch-migration extension pre-module-split (via core/envvars) 2026-07-24
|
||||
github.com/larksuite/cli/events github.com/larksuite/cli/shortcuts/im/convert_lib arch-migration events root aggregates the existing im conversion dependency 2026-07-24
|
||||
github.com/larksuite/cli/events github.com/larksuite/cli/shortcuts/common arch-migration events root aggregates the existing im conversion dependency 2026-07-24
|
||||
github.com/larksuite/cli/events/im github.com/larksuite/cli/shortcuts/im/convert_lib arch-migration events->shortcuts inversion via convert_lib 2026-07-24
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
"github.com/larksuite/cli/envnames"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -35,7 +35,7 @@ func init() {
|
||||
// isolation that this binary cannot provide. Factored out from init() so
|
||||
// tests can exercise the decision without actually calling os.Exit.
|
||||
func checkNoAuthsidecarBuild(getenv func(string) string, stderr io.Writer) int {
|
||||
v := getenv(envvars.CliAuthProxy)
|
||||
v := getenv(envnames.CliAuthProxy)
|
||||
if v == "" {
|
||||
return 0
|
||||
}
|
||||
@@ -49,6 +49,6 @@ func checkNoAuthsidecarBuild(getenv func(string) string, stderr io.Writer) int {
|
||||
"To fix, either:\n"+
|
||||
" - rebuild the CLI with: go build -tags authsidecar\n"+
|
||||
" - or unset %s if sidecar isolation is not required\n",
|
||||
envvars.CliAuthProxy, envvars.CliAuthProxy)
|
||||
envnames.CliAuthProxy, envnames.CliAuthProxy)
|
||||
return 2
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
"github.com/larksuite/cli/envnames"
|
||||
)
|
||||
|
||||
func TestCheckNoAuthsidecarBuild_Unset(t *testing.T) {
|
||||
@@ -30,7 +30,7 @@ func TestCheckNoAuthsidecarBuild_Unset(t *testing.T) {
|
||||
func TestCheckNoAuthsidecarBuild_Set(t *testing.T) {
|
||||
var stderr bytes.Buffer
|
||||
env := func(k string) string {
|
||||
if k == envvars.CliAuthProxy {
|
||||
if k == envnames.CliAuthProxy {
|
||||
return "http://127.0.0.1:16384"
|
||||
}
|
||||
return ""
|
||||
@@ -41,7 +41,7 @@ func TestCheckNoAuthsidecarBuild_Set(t *testing.T) {
|
||||
}
|
||||
msg := stderr.String()
|
||||
for _, want := range []string{
|
||||
envvars.CliAuthProxy,
|
||||
envnames.CliAuthProxy,
|
||||
"authsidecar", // build-tag name must appear so operators can act on it
|
||||
"rebuild",
|
||||
} {
|
||||
|
||||
@@ -17,10 +17,10 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
extcred "github.com/larksuite/cli/extension/credential"
|
||||
"github.com/larksuite/cli/internal/core"
|
||||
"github.com/larksuite/cli/internal/credential"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
"github.com/larksuite/cli/sidecar"
|
||||
)
|
||||
|
||||
@@ -410,13 +410,13 @@ func TestProxyHandler_AcceptsAllowedAuthHeaders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRun_RejectsSelfProxy(t *testing.T) {
|
||||
old, had := os.LookupEnv(envvars.CliAuthProxy)
|
||||
os.Setenv(envvars.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
old, had := os.LookupEnv(envnames.CliAuthProxy)
|
||||
os.Setenv(envnames.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
defer func() {
|
||||
if had {
|
||||
os.Setenv(envvars.CliAuthProxy, old)
|
||||
os.Setenv(envnames.CliAuthProxy, old)
|
||||
} else {
|
||||
os.Unsetenv(envvars.CliAuthProxy)
|
||||
os.Unsetenv(envnames.CliAuthProxy)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -424,8 +424,8 @@ func TestRun_RejectsSelfProxy(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatal("expected error when AUTH_PROXY is set")
|
||||
}
|
||||
if !strings.Contains(err.Error(), envvars.CliAuthProxy) {
|
||||
t.Errorf("error should mention %s, got: %v", envvars.CliAuthProxy, err)
|
||||
if !strings.Contains(err.Error(), envnames.CliAuthProxy) {
|
||||
t.Errorf("error should mention %s, got: %v", envnames.CliAuthProxy, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
"github.com/larksuite/cli/internal/cmdutil"
|
||||
"github.com/larksuite/cli/internal/core"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
"github.com/larksuite/cli/internal/vfs"
|
||||
"github.com/larksuite/cli/sidecar"
|
||||
)
|
||||
@@ -62,8 +62,8 @@ func run(ctx context.Context, listen, keyFile, logFile, profile string) error {
|
||||
// Reject self-proxy: if this process inherited AUTH_PROXY, the sidecar
|
||||
// credential provider would activate and return sentinel tokens instead
|
||||
// of real ones, breaking the "trusted side holds real credentials" premise.
|
||||
if v := os.Getenv(envvars.CliAuthProxy); v != "" {
|
||||
return fmt.Errorf("%s is set in this environment (%s); unset it before starting the sidecar server", envvars.CliAuthProxy, v)
|
||||
if v := os.Getenv(envnames.CliAuthProxy); v != "" {
|
||||
return fmt.Errorf("%s is set in this environment (%s); unset it before starting the sidecar server", envnames.CliAuthProxy, v)
|
||||
}
|
||||
if listen == "" {
|
||||
return fmt.Errorf("invalid --listen address: empty")
|
||||
@@ -155,10 +155,10 @@ func run(ctx context.Context, listen, keyFile, logFile, profile string) error {
|
||||
fmt.Fprintf(os.Stderr, "HMAC key prefix: %s\n", keyPrefix)
|
||||
fmt.Fprintf(os.Stderr, "Full key written to %s (mode 0600)\n", keyFile)
|
||||
fmt.Fprintf(os.Stderr, "\nSet in sandbox:\n")
|
||||
fmt.Fprintf(os.Stderr, " export %s=%q\n", envvars.CliAuthProxy, proxyURL)
|
||||
fmt.Fprintf(os.Stderr, " export %s=\"<read from %s>\"\n", envvars.CliProxyKey, keyFile)
|
||||
fmt.Fprintf(os.Stderr, " export %s=%q\n", envvars.CliAppID, cfg.AppID)
|
||||
fmt.Fprintf(os.Stderr, " export %s=%q\n", envvars.CliBrand, string(cfg.Brand))
|
||||
fmt.Fprintf(os.Stderr, " export %s=%q\n", envnames.CliAuthProxy, proxyURL)
|
||||
fmt.Fprintf(os.Stderr, " export %s=\"<read from %s>\"\n", envnames.CliProxyKey, keyFile)
|
||||
fmt.Fprintf(os.Stderr, " export %s=%q\n", envnames.CliAppID, cfg.AppID)
|
||||
fmt.Fprintf(os.Stderr, " export %s=%q\n", envnames.CliBrand, string(cfg.Brand))
|
||||
|
||||
if err := server.Serve(listener); err != nil && err != http.ErrServerClosed {
|
||||
return fmt.Errorf("sidecar server exited unexpectedly: %v", err)
|
||||
|
||||
@@ -19,10 +19,10 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
extcred "github.com/larksuite/cli/extension/credential"
|
||||
"github.com/larksuite/cli/internal/core"
|
||||
"github.com/larksuite/cli/internal/credential"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
"github.com/larksuite/cli/sidecar"
|
||||
)
|
||||
|
||||
@@ -412,7 +412,7 @@ func TestProxyHandler_AcceptsAllowedAuthHeaders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRun_RejectsSelfProxy(t *testing.T) {
|
||||
t.Setenv(envvars.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
t.Setenv(envnames.CliAuthProxy, "http://127.0.0.1:16384")
|
||||
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
|
||||
keyPath := filepath.Join(t.TempDir(), "proxy.key")
|
||||
|
||||
@@ -420,8 +420,8 @@ func TestRun_RejectsSelfProxy(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatal("expected error when AUTH_PROXY is set")
|
||||
}
|
||||
if !strings.Contains(err.Error(), envvars.CliAuthProxy) {
|
||||
t.Errorf("error should mention %s, got: %v", envvars.CliAuthProxy, err)
|
||||
if !strings.Contains(err.Error(), envnames.CliAuthProxy) {
|
||||
t.Errorf("error should mention %s, got: %v", envnames.CliAuthProxy, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/larksuite/cli/envnames"
|
||||
"github.com/larksuite/cli/internal/cmdutil"
|
||||
"github.com/larksuite/cli/internal/core"
|
||||
"github.com/larksuite/cli/internal/envvars"
|
||||
"github.com/larksuite/cli/internal/validate"
|
||||
"github.com/larksuite/cli/internal/vfs"
|
||||
"github.com/larksuite/cli/sidecar"
|
||||
@@ -62,8 +62,8 @@ func defaultKeyFile() string {
|
||||
}
|
||||
|
||||
func run(ctx context.Context, listen, keyFile, keysDir, logFile, profile string) error {
|
||||
if v := os.Getenv(envvars.CliAuthProxy); v != "" {
|
||||
return fmt.Errorf("%s is set in this environment (%s); unset it before starting the sidecar server", envvars.CliAuthProxy, v)
|
||||
if v := os.Getenv(envnames.CliAuthProxy); v != "" {
|
||||
return fmt.Errorf("%s is set in this environment (%s); unset it before starting the sidecar server", envnames.CliAuthProxy, v)
|
||||
}
|
||||
if listen == "" {
|
||||
return fmt.Errorf("invalid --listen address: empty")
|
||||
@@ -183,10 +183,10 @@ func run(ctx context.Context, listen, keyFile, keysDir, logFile, profile string)
|
||||
fmt.Fprintf(os.Stderr, "Full key written to %s (mode 0600)\n", keyFile)
|
||||
fmt.Fprintf(os.Stderr, "Client keys dir: %s\n", keysDir)
|
||||
fmt.Fprintf(os.Stderr, "\nSet in sandbox:\n")
|
||||
fmt.Fprintf(os.Stderr, " export %s=%q\n", envvars.CliAuthProxy, proxyURL)
|
||||
fmt.Fprintf(os.Stderr, " export %s=\"<read from %s>\"\n", envvars.CliProxyKey, keyFile)
|
||||
fmt.Fprintf(os.Stderr, " export %s=%q\n", envvars.CliAppID, cfg.AppID)
|
||||
fmt.Fprintf(os.Stderr, " export %s=%q\n", envvars.CliBrand, string(cfg.Brand))
|
||||
fmt.Fprintf(os.Stderr, " export %s=%q\n", envnames.CliAuthProxy, proxyURL)
|
||||
fmt.Fprintf(os.Stderr, " export %s=\"<read from %s>\"\n", envnames.CliProxyKey, keyFile)
|
||||
fmt.Fprintf(os.Stderr, " export %s=%q\n", envnames.CliAppID, cfg.AppID)
|
||||
fmt.Fprintf(os.Stderr, " export %s=%q\n", envnames.CliBrand, string(cfg.Brand))
|
||||
|
||||
if err := server.Serve(listener); err != nil && err != http.ErrServerClosed {
|
||||
return fmt.Errorf("sidecar server exited unexpectedly: %v", err)
|
||||
|
||||
Reference in New Issue
Block a user