diff --git a/cli/azd/cmd/auth_login.go b/cli/azd/cmd/auth_login.go index 242891b64bb..c0d712f0023 100644 --- a/cli/azd/cmd/auth_login.go +++ b/cli/azd/cmd/auth_login.go @@ -26,6 +26,7 @@ import ( "github.com/azure/azure-dev/cli/azd/pkg/input" "github.com/azure/azure-dev/cli/azd/pkg/oneauth" "github.com/azure/azure-dev/cli/azd/pkg/output" + "github.com/azure/azure-dev/cli/azd/pkg/output/ux" "github.com/azure/azure-dev/cli/azd/pkg/tools/github" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -318,14 +319,28 @@ func (la *loginAction) Run(ctx context.Context) (*actions.ActionResult, error) { var msg string switch res.Status { case contracts.LoginStatusSuccess: - msg = "Logged in to Azure." + msg = "Logged in to Azure" case contracts.LoginStatusUnauthenticated: - msg = "Not logged in, run `azd auth login` to login to Azure." + msg = "Not logged in, run `azd auth login` to login to Azure" default: panic("Unhandled login status") } - fmt.Fprintln(la.console.Handles().Stdout, msg) + // get user account information - login --check-status + details, err := la.authManager.LogInDetails(ctx) + + // error getting user account or not logged in + if err != nil { + log.Printf("error: getting signed in account: %v", err) + fmt.Fprintln(la.console.Handles().Stdout, msg) + return nil, nil + } + + // only print the message if the user is logged in + la.console.MessageUxItem(ctx, &ux.LoggedIn{ + LoggedInAs: details.Account, + LoginType: ux.LoginType(details.LoginType), + }) return nil, nil } } @@ -354,7 +369,18 @@ func (la *loginAction) Run(ctx context.Context) (*actions.ActionResult, error) { } } - la.console.Message(ctx, "Logged in to Azure.") + details, err := la.authManager.LogInDetails(ctx) + + // error getting user account, successful log in + if err != nil { + log.Printf("error: getting signed in account: %v", err) + la.console.Message(ctx, "Logged in to Azure") + return nil, nil + } + la.console.MessageUxItem(ctx, &ux.LoggedIn{ + LoggedInAs: details.Account, + LoginType: ux.LoginType(details.LoginType), + }) return nil, nil } diff --git a/cli/azd/pkg/auth/manager.go b/cli/azd/pkg/auth/manager.go index c051e3820a1..a6eca564cde 100644 --- a/cli/azd/pkg/auth/manager.go +++ b/cli/azd/pkg/auth/manager.go @@ -1134,3 +1134,50 @@ func readUserProperties(cfg config.Config) (*userProperties, error) { return &user, nil } + +const ( + EmailLoginType LoginType = "email" + ClientIdLoginType LoginType = "clientId" +) + +type LoginType string + +type LogInDetails struct { + LoginType LoginType + Account string +} + +// LogInDetails method for Manager to return login details +func (m *Manager) LogInDetails(ctx context.Context) (*LogInDetails, error) { + cfg, err := m.readAuthConfig() + if err != nil { + return nil, fmt.Errorf("fetching current user: %w", err) + } + + currentUser, err := readUserProperties(cfg) + if err != nil { + return nil, ErrNoCurrentUser + } + + if currentUser.HomeAccountID != nil { + accounts, err := m.publicClient.Accounts(ctx) + if err != nil { + return nil, err + } + for _, account := range accounts { + if account.HomeAccountID == *currentUser.HomeAccountID { + return &LogInDetails{ + LoginType: EmailLoginType, + Account: account.PreferredUsername, + }, nil + } + } + } else if currentUser.ClientID != nil { + return &LogInDetails{ + LoginType: ClientIdLoginType, + Account: *currentUser.ClientID, + }, nil + } + + return nil, ErrNoCurrentUser +} diff --git a/cli/azd/pkg/output/ux/logged_in.go b/cli/azd/pkg/output/ux/logged_in.go new file mode 100644 index 00000000000..59decaf2c4d --- /dev/null +++ b/cli/azd/pkg/output/ux/logged_in.go @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package ux + +import ( + "encoding/json" + "fmt" + + "github.com/azure/azure-dev/cli/azd/pkg/output" +) + +const cLoginSuccessMessage = "Logged in to Azure" +const ( + EmailLoginType LoginType = "email" + ClientIdLoginType LoginType = "clientId" +) + +type LoginType string + +type LoggedIn struct { + LoggedInAs string + LoginType LoginType +} + +func (cr *LoggedIn) ToString(currentIndentation string) string { + switch cr.LoginType { + case EmailLoginType: + return fmt.Sprintf( + "%s%s as %s", + currentIndentation, + cLoginSuccessMessage, + output.WithBold("%s", cr.LoggedInAs)) + case ClientIdLoginType: + return fmt.Sprintf( + "%s%s as (%s)", + currentIndentation, + cLoginSuccessMessage, + output.WithGrayFormat("%s", cr.LoggedInAs)) + default: + } + + return fmt.Sprintf( + "%s%s", + currentIndentation, + cLoginSuccessMessage) +} + +func (cr *LoggedIn) MarshalJSON() ([]byte, error) { + // reusing the same envelope from console messages + return json.Marshal(output.EventForMessage( + fmt.Sprintf("%s as %s", cLoginSuccessMessage, cr.LoggedInAs))) +}