Skip to content

Commit 80b357c

Browse files
authored
Merge branch 'main' into fix-cua-templates-scroll-behavior
2 parents c1cd6c6 + 43fc638 commit 80b357c

2 files changed

Lines changed: 166 additions & 0 deletions

File tree

cmd/auth_connections.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,37 @@ func (c AuthConnectionCmd) Submit(ctx context.Context, in AuthConnectionSubmitIn
450450
return fmt.Errorf("must provide at least one of: --field, --mfa-option-id, or --sso-button-selector")
451451
}
452452

453+
// Resolve MFA option: the user may pass the label (e.g. "Get a text"), the
454+
// type (e.g. "sms"), or the display string ("Get a text (sms)"). The API
455+
// expects the type, so look up the connection's available options and map
456+
// whatever the user provided to the correct type value.
457+
if hasMfaOption {
458+
conn, err := c.svc.Get(ctx, in.ID)
459+
if err != nil {
460+
return util.CleanedUpSdkError{Err: fmt.Errorf("failed to fetch connection for MFA option resolution: %w", err)}
461+
}
462+
if len(conn.MfaOptions) > 0 {
463+
resolved := false
464+
for _, opt := range conn.MfaOptions {
465+
displayName := fmt.Sprintf("%s (%s)", opt.Label, opt.Type)
466+
if strings.EqualFold(in.MfaOptionID, opt.Type) ||
467+
strings.EqualFold(in.MfaOptionID, opt.Label) ||
468+
strings.EqualFold(in.MfaOptionID, displayName) {
469+
in.MfaOptionID = opt.Type
470+
resolved = true
471+
break
472+
}
473+
}
474+
if !resolved {
475+
available := make([]string, 0, len(conn.MfaOptions))
476+
for _, opt := range conn.MfaOptions {
477+
available = append(available, fmt.Sprintf("%s (%s)", opt.Label, opt.Type))
478+
}
479+
return fmt.Errorf("unknown MFA option %q; available: %s", in.MfaOptionID, strings.Join(available, ", "))
480+
}
481+
}
482+
}
483+
453484
params := kernel.AuthConnectionSubmitParams{
454485
SubmitFieldsRequest: kernel.SubmitFieldsRequestParam{
455486
Fields: in.FieldValues,

cmd/auth_connections_test.go

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,138 @@ func TestAuthConnectionsList_JSONOutput_PrintsRawResponse(t *testing.T) {
196196
assert.Contains(t, out, "\"profile_name\"")
197197
assert.Contains(t, out, "\"raf-leaseweb\"")
198198
}
199+
200+
func newFakeWithMfaOptions(options []kernel.ManagedAuthMfaOption) *FakeAuthConnectionService {
201+
return &FakeAuthConnectionService{
202+
GetFunc: func(ctx context.Context, id string, opts ...option.RequestOption) (*kernel.ManagedAuth, error) {
203+
return &kernel.ManagedAuth{
204+
ID: id,
205+
MfaOptions: options,
206+
}, nil
207+
},
208+
SubmitFunc: func(ctx context.Context, id string, body kernel.AuthConnectionSubmitParams, opts ...option.RequestOption) (*kernel.SubmitFieldsResponse, error) {
209+
return &kernel.SubmitFieldsResponse{Accepted: true}, nil
210+
},
211+
}
212+
}
213+
214+
func TestSubmit_MfaOptionResolvesType(t *testing.T) {
215+
fake := newFakeWithMfaOptions([]kernel.ManagedAuthMfaOption{
216+
{Label: "Get a text", Type: "sms"},
217+
{Label: "Have us call you", Type: "call"},
218+
})
219+
220+
var submittedID string
221+
fake.SubmitFunc = func(ctx context.Context, id string, body kernel.AuthConnectionSubmitParams, opts ...option.RequestOption) (*kernel.SubmitFieldsResponse, error) {
222+
submittedID = body.SubmitFieldsRequest.MfaOptionID.Value
223+
return &kernel.SubmitFieldsResponse{Accepted: true}, nil
224+
}
225+
226+
c := AuthConnectionCmd{svc: fake}
227+
err := c.Submit(context.Background(), AuthConnectionSubmitInput{
228+
ID: "conn-1",
229+
MfaOptionID: "sms",
230+
Output: "json",
231+
})
232+
require.NoError(t, err)
233+
assert.Equal(t, "sms", submittedID)
234+
}
235+
236+
func TestSubmit_MfaOptionResolvesLabel(t *testing.T) {
237+
fake := newFakeWithMfaOptions([]kernel.ManagedAuthMfaOption{
238+
{Label: "Get a text", Type: "sms"},
239+
{Label: "Have us call you", Type: "call"},
240+
})
241+
242+
var submittedID string
243+
fake.SubmitFunc = func(ctx context.Context, id string, body kernel.AuthConnectionSubmitParams, opts ...option.RequestOption) (*kernel.SubmitFieldsResponse, error) {
244+
submittedID = body.SubmitFieldsRequest.MfaOptionID.Value
245+
return &kernel.SubmitFieldsResponse{Accepted: true}, nil
246+
}
247+
248+
c := AuthConnectionCmd{svc: fake}
249+
err := c.Submit(context.Background(), AuthConnectionSubmitInput{
250+
ID: "conn-1",
251+
MfaOptionID: "Get a text",
252+
Output: "json",
253+
})
254+
require.NoError(t, err)
255+
assert.Equal(t, "sms", submittedID)
256+
}
257+
258+
func TestSubmit_MfaOptionResolvesDisplayString(t *testing.T) {
259+
fake := newFakeWithMfaOptions([]kernel.ManagedAuthMfaOption{
260+
{Label: "Get a text", Type: "sms"},
261+
})
262+
263+
var submittedID string
264+
fake.SubmitFunc = func(ctx context.Context, id string, body kernel.AuthConnectionSubmitParams, opts ...option.RequestOption) (*kernel.SubmitFieldsResponse, error) {
265+
submittedID = body.SubmitFieldsRequest.MfaOptionID.Value
266+
return &kernel.SubmitFieldsResponse{Accepted: true}, nil
267+
}
268+
269+
c := AuthConnectionCmd{svc: fake}
270+
err := c.Submit(context.Background(), AuthConnectionSubmitInput{
271+
ID: "conn-1",
272+
MfaOptionID: "Get a text (sms)",
273+
Output: "json",
274+
})
275+
require.NoError(t, err)
276+
assert.Equal(t, "sms", submittedID)
277+
}
278+
279+
func TestSubmit_MfaOptionResolvesLabelCaseInsensitive(t *testing.T) {
280+
fake := newFakeWithMfaOptions([]kernel.ManagedAuthMfaOption{
281+
{Label: "Get a text", Type: "sms"},
282+
})
283+
284+
var submittedID string
285+
fake.SubmitFunc = func(ctx context.Context, id string, body kernel.AuthConnectionSubmitParams, opts ...option.RequestOption) (*kernel.SubmitFieldsResponse, error) {
286+
submittedID = body.SubmitFieldsRequest.MfaOptionID.Value
287+
return &kernel.SubmitFieldsResponse{Accepted: true}, nil
288+
}
289+
290+
c := AuthConnectionCmd{svc: fake}
291+
err := c.Submit(context.Background(), AuthConnectionSubmitInput{
292+
ID: "conn-1",
293+
MfaOptionID: "get a TEXT",
294+
Output: "json",
295+
})
296+
require.NoError(t, err)
297+
assert.Equal(t, "sms", submittedID)
298+
}
299+
300+
func TestSubmit_MfaOptionGetErrorSurfaced(t *testing.T) {
301+
fake := &FakeAuthConnectionService{
302+
GetFunc: func(ctx context.Context, id string, opts ...option.RequestOption) (*kernel.ManagedAuth, error) {
303+
return nil, errors.New("connection not found")
304+
},
305+
}
306+
307+
c := AuthConnectionCmd{svc: fake}
308+
err := c.Submit(context.Background(), AuthConnectionSubmitInput{
309+
ID: "conn-1",
310+
MfaOptionID: "sms",
311+
Output: "json",
312+
})
313+
require.Error(t, err)
314+
assert.Contains(t, err.Error(), "connection not found")
315+
}
316+
317+
func TestSubmit_MfaOptionRejectsUnknown(t *testing.T) {
318+
fake := newFakeWithMfaOptions([]kernel.ManagedAuthMfaOption{
319+
{Label: "Get a text", Type: "sms"},
320+
{Label: "Have us call you", Type: "call"},
321+
})
322+
323+
c := AuthConnectionCmd{svc: fake}
324+
err := c.Submit(context.Background(), AuthConnectionSubmitInput{
325+
ID: "conn-1",
326+
MfaOptionID: "carrier pigeon",
327+
Output: "json",
328+
})
329+
require.Error(t, err)
330+
assert.Contains(t, err.Error(), "unknown MFA option")
331+
assert.Contains(t, err.Error(), "carrier pigeon")
332+
assert.Contains(t, err.Error(), "Get a text (sms)")
333+
}

0 commit comments

Comments
 (0)