feat(login): use account chosen on the device-approval page; stdin picker becomes fallback
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
098a2091b9
commit
2b685348c9
@ -57,10 +57,14 @@ func newLoginCmd() *cobra.Command {
|
|||||||
cr.Hosts = map[string]creds.HostCreds{}
|
cr.Hosts = map[string]creds.HostCreds{}
|
||||||
}
|
}
|
||||||
hc := creds.HostCreds{Token: poll.Msg.AccessToken}
|
hc := creds.HostCreds{Token: poll.Msg.AccessToken}
|
||||||
|
if applyPolledAccount(&hc, poll.Msg.AccountId, poll.Msg.AccountSlug) {
|
||||||
|
fmt.Printf("Active account: %s\n", hc.ActiveAccountSlug)
|
||||||
|
} else {
|
||||||
authed := orchclient.New(host, hc.Token)
|
authed := orchclient.New(host, hc.Token)
|
||||||
if err := selectActiveAccount(ctx, authed, &hc); err != nil {
|
if err := selectActiveAccount(ctx, authed, &hc); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cr.Hosts[host] = hc
|
cr.Hosts[host] = hc
|
||||||
if err := cr.Save(); err != nil {
|
if err := cr.Save(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -103,6 +107,18 @@ func newWhoamiCmd() *cobra.Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// applyPolledAccount copies the account chosen on the device-approval page
|
||||||
|
// into hc. Returns false when the server sent no account (older orchestrator,
|
||||||
|
// or an approval without a selection) — the stdin picker should run instead.
|
||||||
|
func applyPolledAccount(hc *creds.HostCreds, accountID, accountSlug string) bool {
|
||||||
|
if accountID == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
hc.ActiveAccountID = accountID
|
||||||
|
hc.ActiveAccountSlug = accountSlug
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// selectActiveAccount fetches the user's accounts and writes the active one
|
// selectActiveAccount fetches the user's accounts and writes the active one
|
||||||
// into hc. With 0 accounts it errors (the server contract guarantees every
|
// into hc. With 0 accounts it errors (the server contract guarantees every
|
||||||
// user has at least one). With 1 it auto-selects silently. With ≥2 it
|
// user has at least one). With 1 it auto-selects silently. With ≥2 it
|
||||||
|
|||||||
27
cmd/ninja/cmd/login_test.go
Normal file
27
cmd/ninja/cmd/login_test.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.dev.alexdunmow.com/block/cli/internal/creds"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestApplyPolledAccount_Set(t *testing.T) {
|
||||||
|
hc := creds.HostCreds{Token: "tok"}
|
||||||
|
if !applyPolledAccount(&hc, "acct-id-1", "blockninja") {
|
||||||
|
t.Fatal("want true when server supplies an account")
|
||||||
|
}
|
||||||
|
if hc.ActiveAccountID != "acct-id-1" || hc.ActiveAccountSlug != "blockninja" {
|
||||||
|
t.Fatalf("hc = %+v, want active account set", hc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplyPolledAccount_EmptyFallsThrough(t *testing.T) {
|
||||||
|
hc := creds.HostCreds{Token: "tok"}
|
||||||
|
if applyPolledAccount(&hc, "", "") {
|
||||||
|
t.Fatal("want false when server sent no account (older orchestrator)")
|
||||||
|
}
|
||||||
|
if hc.ActiveAccountID != "" || hc.ActiveAccountSlug != "" {
|
||||||
|
t.Fatalf("hc = %+v, want untouched", hc)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5326,6 +5326,8 @@ type PollDeviceResponse struct {
|
|||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
|
AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
|
||||||
Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
|
Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
|
||||||
|
AccountId string `protobuf:"bytes,3,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
|
||||||
|
AccountSlug string `protobuf:"bytes,4,opt,name=account_slug,json=accountSlug,proto3" json:"account_slug,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@ -5374,9 +5376,24 @@ func (x *PollDeviceResponse) GetStatus() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *PollDeviceResponse) GetAccountId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.AccountId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PollDeviceResponse) GetAccountSlug() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.AccountSlug
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type ApproveDeviceRequest struct {
|
type ApproveDeviceRequest struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
UserCode string `protobuf:"bytes,1,opt,name=user_code,json=userCode,proto3" json:"user_code,omitempty"`
|
UserCode string `protobuf:"bytes,1,opt,name=user_code,json=userCode,proto3" json:"user_code,omitempty"`
|
||||||
|
AccountId string `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@ -5418,6 +5435,13 @@ func (x *ApproveDeviceRequest) GetUserCode() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *ApproveDeviceRequest) GetAccountId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.AccountId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type ApproveDeviceResponse struct {
|
type ApproveDeviceResponse struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
@ -6290,12 +6314,17 @@ const file_orchestrator_v1_plugin_registry_proto_rawDesc = "" +
|
|||||||
"\x12expires_in_seconds\x18\x05 \x01(\x05R\x10expiresInSeconds\"4\n" +
|
"\x12expires_in_seconds\x18\x05 \x01(\x05R\x10expiresInSeconds\"4\n" +
|
||||||
"\x11PollDeviceRequest\x12\x1f\n" +
|
"\x11PollDeviceRequest\x12\x1f\n" +
|
||||||
"\vdevice_code\x18\x01 \x01(\tR\n" +
|
"\vdevice_code\x18\x01 \x01(\tR\n" +
|
||||||
"deviceCode\"O\n" +
|
"deviceCode\"\x91\x01\n" +
|
||||||
"\x12PollDeviceResponse\x12!\n" +
|
"\x12PollDeviceResponse\x12!\n" +
|
||||||
"\faccess_token\x18\x01 \x01(\tR\vaccessToken\x12\x16\n" +
|
"\faccess_token\x18\x01 \x01(\tR\vaccessToken\x12\x16\n" +
|
||||||
"\x06status\x18\x02 \x01(\tR\x06status\"3\n" +
|
"\x06status\x18\x02 \x01(\tR\x06status\x12\x1d\n" +
|
||||||
|
"\n" +
|
||||||
|
"account_id\x18\x03 \x01(\tR\taccountId\x12!\n" +
|
||||||
|
"\faccount_slug\x18\x04 \x01(\tR\vaccountSlug\"R\n" +
|
||||||
"\x14ApproveDeviceRequest\x12\x1b\n" +
|
"\x14ApproveDeviceRequest\x12\x1b\n" +
|
||||||
"\tuser_code\x18\x01 \x01(\tR\buserCode\"\x17\n" +
|
"\tuser_code\x18\x01 \x01(\tR\buserCode\x12\x1d\n" +
|
||||||
|
"\n" +
|
||||||
|
"account_id\x18\x02 \x01(\tR\taccountId\"\x17\n" +
|
||||||
"\x15ApproveDeviceResponse\"0\n" +
|
"\x15ApproveDeviceResponse\"0\n" +
|
||||||
"\x11DenyDeviceRequest\x12\x1b\n" +
|
"\x11DenyDeviceRequest\x12\x1b\n" +
|
||||||
"\tuser_code\x18\x01 \x01(\tR\buserCode\"\x14\n" +
|
"\tuser_code\x18\x01 \x01(\tR\buserCode\"\x14\n" +
|
||||||
|
|||||||
@ -650,9 +650,14 @@ message PollDeviceRequest { string device_code = 1; }
|
|||||||
message PollDeviceResponse {
|
message PollDeviceResponse {
|
||||||
string access_token = 1;
|
string access_token = 1;
|
||||||
string status = 2;
|
string status = 2;
|
||||||
|
string account_id = 3;
|
||||||
|
string account_slug = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ApproveDeviceRequest { string user_code = 1; }
|
message ApproveDeviceRequest {
|
||||||
|
string user_code = 1;
|
||||||
|
string account_id = 2;
|
||||||
|
}
|
||||||
message ApproveDeviceResponse {}
|
message ApproveDeviceResponse {}
|
||||||
|
|
||||||
message DenyDeviceRequest { string user_code = 1; }
|
message DenyDeviceRequest { string user_code = 1; }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user