authLoginPollDeviceCode resumes the device flow by polling with a device code obtained from a previous --no-wait call.
(opts *LoginOptions, config *core.CliConfig, msg *loginMsg, log func(string, ...interface{}))
| 392 | // authLoginPollDeviceCode resumes the device flow by polling with a device code |
| 393 | // obtained from a previous --no-wait call. |
| 394 | func authLoginPollDeviceCode(opts *LoginOptions, config *core.CliConfig, msg *loginMsg, log func(string, ...interface{})) error { |
| 395 | f := opts.Factory |
| 396 | |
| 397 | httpClient, err := f.HttpClient() |
| 398 | if err != nil { |
| 399 | return err |
| 400 | } |
| 401 | requestedScope, err := loadLoginRequestedScope(opts.DeviceCode) |
| 402 | if err != nil { |
| 403 | fmt.Fprintf(f.IOStreams.ErrOut, "[lark-cli] [WARN] auth login: failed to load cached requested scopes: %v\n", err) |
| 404 | } |
| 405 | cleanupRequestedScope := func() { |
| 406 | if err := removeLoginRequestedScope(opts.DeviceCode); err != nil { |
| 407 | fmt.Fprintf(f.IOStreams.ErrOut, "[lark-cli] [WARN] auth login: failed to remove cached requested scopes: %v\n", err) |
| 408 | } |
| 409 | } |
| 410 | // Skip the stderr hint in JSON mode (the --no-wait call that issued |
| 411 | // the device_code already surfaced it as a JSON field), and also skip it |
| 412 | // when running on an interactive terminal — the agent-oriented |
| 413 | // instructions only matter for piped / harness environments. |
| 414 | if !opts.JSON && f.IOStreams != nil && !f.IOStreams.IsTerminal { |
| 415 | fmt.Fprintln(f.IOStreams.ErrOut, msg.AgentTimeoutHint) |
| 416 | } |
| 417 | log(msg.WaitingAuth) |
| 418 | result := pollDeviceToken(opts.Ctx, httpClient, config.AppID, config.AppSecret, config.Brand, |
| 419 | opts.DeviceCode, 5, 600, f.IOStreams.ErrOut) |
| 420 | |
| 421 | if !result.OK { |
| 422 | if shouldRemoveLoginRequestedScope(result) { |
| 423 | cleanupRequestedScope() |
| 424 | } |
| 425 | return errs.NewAuthenticationError(errs.SubtypeUnknown, "authorization failed: %s", result.Message) |
| 426 | } |
| 427 | defer cleanupRequestedScope() |
| 428 | if result.Token == nil { |
| 429 | return errs.NewAuthenticationError(errs.SubtypeTokenMissing, "authorization succeeded but no token returned") |
| 430 | } |
| 431 | |
| 432 | // Get user info |
| 433 | log(msg.AuthSuccess) |
| 434 | sdk, err := f.LarkClient() |
| 435 | if err != nil { |
| 436 | return errs.NewInternalError(errs.SubtypeSDKError, "failed to get SDK: %v", err).WithCause(err) |
| 437 | } |
| 438 | openId, userName, err := getUserInfo(opts.Ctx, sdk, result.Token.AccessToken) |
| 439 | if err != nil { |
| 440 | return errs.NewAuthenticationError(errs.SubtypeUnknown, "failed to get user info: %v", err).WithCause(err) |
| 441 | } |
| 442 | |
| 443 | scopeSummary := loadLoginScopeSummary(config.AppID, openId, requestedScope, result.Token.Scope) |
| 444 | |
| 445 | // Store token |
| 446 | now := time.Now().UnixMilli() |
| 447 | storedToken := &larkauth.StoredUAToken{ |
| 448 | UserOpenId: openId, |
| 449 | AppId: config.AppID, |
| 450 | AccessToken: result.Token.AccessToken, |
| 451 | RefreshToken: result.Token.RefreshToken, |
no test coverage detected