@@ -17,7 +17,6 @@ import (
1717
1818var accountTypes = []string {"DeepSource (deepsource.com)" , "Enterprise Server" }
1919
20- // LoginOptions hold the metadata related to login operation
2120type LoginOptions struct {
2221 AuthTimedOut bool
2322 TokenExpired bool
@@ -28,12 +27,10 @@ type LoginOptions struct {
2827 deps * cmddeps.Deps
2928}
3029
31- // NewCmdLogin handles the login functionality for the CLI
3230func NewCmdLogin () * cobra.Command {
3331 return NewCmdLoginWithDeps (nil )
3432}
3533
36- // NewCmdLoginWithDeps creates the login command with injectable dependencies.
3734func NewCmdLoginWithDeps (deps * cmddeps.Deps ) * cobra.Command {
3835 doc := heredoc .Docf (`
3936 Log in to DeepSource using the CLI.
@@ -66,7 +63,6 @@ func NewCmdLoginWithDeps(deps *cmddeps.Deps) *cobra.Command {
6663 },
6764 }
6865
69- // --host flag (--hostname kept as deprecated alias)
7066 cmd .Flags ().StringVar (& opts .HostName , "host" , "" , "Authenticate with a specific DeepSource instance" )
7167 cmd .Flags ().StringVar (& opts .HostName , "hostname" , "" , "Authenticate with a specific DeepSource instance" )
7268 _ = cmd .Flags ().MarkDeprecated ("hostname" , "use --host instead" )
@@ -76,7 +72,6 @@ func NewCmdLoginWithDeps(deps *cmddeps.Deps) *cobra.Command {
7672 return cmd
7773}
7874
79- // Run executes the auth command and starts the login flow if not already authenticated
8075func (opts * LoginOptions ) Run () (err error ) {
8176 var cfgMgr * config.Manager
8277 if opts .deps != nil && opts .deps .ConfigMgr != nil {
@@ -92,92 +87,78 @@ func (opts *LoginOptions) Run() (err error) {
9287 } else {
9388 svc = authsvc .NewService (cfgMgr )
9489 }
95- // Fetch config (errors are non-fatal: a zero config just means "not logged in")
9690 cfg , err := svc .LoadConfig ()
9791 if err != nil {
98- cfg = & config.CLIConfig {}
92+ cfg = config .NewDefault ()
9993 }
10094 opts .User = cfg .User
10195 opts .TokenExpired = cfg .IsExpired ()
10296
103- // If local says valid, verify against the server
104- opts .verifyTokenWithServer (cfg , cfgMgr )
97+ opts .verifyTokenWithServer (cfg , svc )
10598
106- // Login using the interactive mode
10799 if opts .Interactive {
108100 err = opts .handleInteractiveLogin ()
109101 if err != nil {
110102 return err
111103 }
112104 }
113105
114- // Checking if the user passed a hostname. If yes, storing it in the config
115- // Else using the default hostname (deepsource.com)
116106 if opts .HostName != "" {
117107 cfg .Host = opts .HostName
118108 } else {
119109 cfg .Host = config .DefaultHostName
120110 }
121111
122- // If PAT is passed, start the login flow through PAT (skip interactive prompts)
123112 if opts .PAT != "" {
124113 return opts .startPATLoginFlow (svc , cfg , opts .PAT )
125114 }
126115
127- // Before starting the login workflow, check here for two conditions:
128- // Condition 1 : If the token has expired, display a message about it and re-authenticate user
129- // Condition 2 : If the token has not expired,does the user want to re-authenticate?
130-
131- // Checking for condition 1
132116 if ! opts .TokenExpired {
133- // The user is already logged in, confirm re-authentication.
134- msg := fmt .Sprintf ("You're already logged into DeepSource as %s. Do you want to re-authenticate?" , opts .User )
117+ var msg string
118+ if opts .User != "" {
119+ msg = fmt .Sprintf ("You're already logged into DeepSource as %s. Do you want to re-authenticate?" , opts .User )
120+ } else {
121+ msg = "You're already logged into DeepSource. Do you want to re-authenticate?"
122+ }
135123 response , err := prompt .ConfirmFromUser (msg , "" )
136124 if err != nil {
137125 return fmt .Errorf ("Error in fetching response. Please try again." )
138126 }
139- // If the response is No, it implies that the user doesn't want to re-authenticate
140- // In this case, just exit
141127 if ! response {
142128 return nil
143129 }
144130 }
145131
146- // Condition 2
147- // `startLoginFlow` implements the authentication flow for the CLI
148132 return opts .startLoginFlow (svc , cfg )
149133}
150134
151- func (opts * LoginOptions ) verifyTokenWithServer (cfg * config.CLIConfig , cfgMgr * config. Manager ) {
152- if opts .TokenExpired || cfg .Token == "" || cfg . Host == "" {
135+ func (opts * LoginOptions ) verifyTokenWithServer (cfg * config.CLIConfig , svc * authsvc. Service ) {
136+ if opts .TokenExpired || cfg .Token == "" {
153137 return
154138 }
155- client , err := deepsource .New (deepsource.ClientOpts {
156- Token : cfg .Token ,
157- HostName : cfg .Host ,
158- OnTokenRefreshed : cfgMgr .TokenRefreshCallback (),
159- })
139+ viewer , err := svc .GetViewer (context .Background (), cfg )
160140 if err != nil {
141+ opts .TokenExpired = true
161142 return
162143 }
163- if _ , err := client .GetViewer (context .Background ()); err != nil {
164- opts .TokenExpired = true
144+ // Backfill user from the server when config file was missing or incomplete.
145+ if cfg .User == "" && viewer .Email != "" {
146+ cfg .User = viewer .Email
147+ opts .User = viewer .Email
148+ _ = svc .SaveConfig (cfg )
165149 }
166150}
167151
168152func (opts * LoginOptions ) handleInteractiveLogin () error {
169- // Prompt messages and help texts
170153 loginPromptMessage := "Which account do you want to login into?"
171154 loginPromptHelpText := "Select the type of account you want to authenticate"
172155 hostPromptMessage := "Please enter the hostname:"
173156 hostPromptHelpText := "The hostname of the DeepSource instance to authenticate with"
174157
175- // Display prompt to user
176158 loginType , err := prompt .SelectFromOptions (loginPromptMessage , loginPromptHelpText , accountTypes )
177159 if err != nil {
178160 return err
179161 }
180- // Prompt the user for hostname only in the case of on-premise
181162 if loginType == "Enterprise Server" {
182163 opts .HostName , err = prompt .GetSingleLineInput (hostPromptMessage , hostPromptHelpText )
183164 if err != nil {
0 commit comments