Skip to content

Commit fd669a4

Browse files
committed
feat: show organization name in whoami output
1 parent 8bcd612 commit fd669a4

2 files changed

Lines changed: 52 additions & 4 deletions

File tree

cmd/whoami/whoami.go

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ type memberSummary struct {
3939
Role string `json:"role"`
4040
}
4141

42+
type accountSummary struct {
43+
Organization string `json:"organization"`
44+
}
45+
4246
func NewWhoAmICmd(client resources.Client) *cobra.Command {
4347
cmd := &cobra.Command{
4448
Args: cobra.NoArgs,
@@ -119,12 +123,25 @@ func makeRequest(client resources.Client) func(*cobra.Command, []string) error {
119123
}
120124
}
121125

122-
fmt.Fprint(cmd.OutOrStdout(), formatPlaintext(identity, member)+"\n")
126+
// Fetch the account to resolve the organization name. This endpoint is a
127+
// real public-API route but isn't published in the OpenAPI spec, so we
128+
// treat it as best-effort and fall back to the account ID on any failure.
129+
var account *accountSummary
130+
accountPath, _ := url.JoinPath(baseURI, "api/v2/account")
131+
accountRes, err := client.MakeRequest(accessToken, "GET", accountPath, "application/json", nil, nil, false)
132+
if err == nil {
133+
var a accountSummary
134+
if json.Unmarshal(accountRes, &a) == nil {
135+
account = &a
136+
}
137+
}
138+
139+
fmt.Fprint(cmd.OutOrStdout(), formatPlaintext(identity, member, account)+"\n")
123140
return nil
124141
}
125142
}
126143

127-
func formatPlaintext(identity callerIdentity, member *memberSummary) string {
144+
func formatPlaintext(identity callerIdentity, member *memberSummary, account *accountSummary) string {
128145
var sb strings.Builder
129146

130147
if member != nil {
@@ -147,7 +164,13 @@ func formatPlaintext(identity callerIdentity, member *memberSummary) string {
147164
fmt.Fprintf(&sb, "Token: %s (%s)\n", identity.ClientID, tokenKind)
148165
}
149166

150-
if identity.AccountID != "" {
167+
if account != nil && account.Organization != "" {
168+
if identity.AccountID != "" {
169+
fmt.Fprintf(&sb, "Account: %s (%s)\n", account.Organization, identity.AccountID)
170+
} else {
171+
fmt.Fprintf(&sb, "Account: %s\n", account.Organization)
172+
}
173+
} else if identity.AccountID != "" {
151174
fmt.Fprintf(&sb, "Account: %s\n", identity.AccountID)
152175
}
153176

cmd/whoami/whoami_test.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ func (c *sequentialMockClient) MakeUnauthenticatedRequest(_ string, _ string, _
3434
}
3535

3636
func TestWhoAmI(t *testing.T) {
37-
t.Run("shows member name, email, role, and token", func(t *testing.T) {
37+
t.Run("shows member name, email, role, token, and organization", func(t *testing.T) {
3838
mockClient := &sequentialMockClient{
3939
responses: [][]byte{
4040
[]byte(`{"memberId": "abc123", "tokenName": "my-token", "tokenKind": "personal", "accountId": "acct1"}`),
4141
[]byte(`{"_id": "abc123", "email": "ariel@acme.com", "firstName": "Ariel", "lastName": "Flores", "role": "admin"}`),
42+
[]byte(`{"_id": "acct1", "organization": "Acme Inc"}`),
4243
},
4344
}
4445

@@ -55,6 +56,30 @@ func TestWhoAmI(t *testing.T) {
5556
assert.Contains(t, string(output), "Ariel Flores <ariel@acme.com>")
5657
assert.Contains(t, string(output), "Role: admin")
5758
assert.Contains(t, string(output), "Token: my-token (personal)")
59+
assert.Contains(t, string(output), "Account: Acme Inc (acct1)")
60+
})
61+
62+
t.Run("falls back to account ID when organization is unavailable", func(t *testing.T) {
63+
mockClient := &sequentialMockClient{
64+
responses: [][]byte{
65+
[]byte(`{"memberId": "abc123", "tokenName": "my-token", "tokenKind": "personal", "accountId": "acct1"}`),
66+
[]byte(`{"_id": "abc123", "email": "ariel@acme.com", "firstName": "Ariel", "lastName": "Flores", "role": "admin"}`),
67+
[]byte(`{"_id": "acct1"}`),
68+
},
69+
}
70+
71+
t.Setenv("LD_ACCESS_TOKEN", "abcd1234")
72+
73+
output, err := cmd.CallCmd(
74+
t,
75+
cmd.APIClients{ResourcesClient: mockClient},
76+
analytics.NoopClientFn{}.Tracker(),
77+
[]string{"whoami"},
78+
)
79+
80+
require.NoError(t, err)
81+
assert.Contains(t, string(output), "Account: acct1")
82+
assert.NotContains(t, string(output), "Account: Acme")
5883
})
5984

6085
t.Run("without member ID shows token info only", func(t *testing.T) {

0 commit comments

Comments
 (0)