/ internal / executor / login.go
login.go
 1  package executor
 2  
 3  import (
 4  	"fmt"
 5  	"strings"
 6  
 7  	"codeflow.dananglin.me.uk/apollo/enbas/internal/config"
 8  	"codeflow.dananglin.me.uk/apollo/enbas/internal/gtsclient"
 9  	"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
10  	"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
11  	"codeflow.dananglin.me.uk/apollo/enbas/internal/server"
12  	"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
13  )
14  
15  func (l *LoginExecutor) Execute() error {
16  	var err error
17  
18  	if l.instance == "" {
19  		return Error{"please specify the instance that you want to log into"}
20  	}
21  
22  	if !strings.HasPrefix(l.instance, "https") || !strings.HasPrefix(l.instance, "http") {
23  		l.instance = "https://" + l.instance
24  	}
25  
26  	for strings.HasSuffix(l.instance, "/") {
27  		l.instance = l.instance[:len(l.instance)-1]
28  	}
29  
30  	client, err := server.Connect(l.config.Server, l.configDir)
31  	if err != nil {
32  		return fmt.Errorf("error creating the client for the daemon process: %w", err)
33  	}
34  	defer client.Close()
35  
36  	// Update the GTSClient's auth details for the registration process.
37  	auth := config.Credentials{
38  		Instance:     l.instance,
39  		ClientID:     "",
40  		ClientSecret: "",
41  		AccessToken:  "",
42  	}
43  
44  	if err := client.Call("GTSClient.UpdateAuthentication", auth, nil); err != nil {
45  		return fmt.Errorf("error updating the GTSClient's authentication details: %w", err)
46  	}
47  
48  	if err := client.Call("GTSClient.Register", gtsclient.NoRPCArgs{}, nil); err != nil {
49  		return fmt.Errorf("unable to register the application: %w", err)
50  	}
51  
52  	var consentPageURL string
53  
54  	if err := client.Call("GTSClient.AuthCodeURL", gtsclient.NoRPCArgs{}, &consentPageURL); err != nil {
55  		return fmt.Errorf("unable to get the URL of the consent page: %w", err)
56  	}
57  
58  	_ = utilities.OpenLink(l.config.Integrations.Browser, consentPageURL)
59  
60  	var builder strings.Builder
61  
62  	builder.WriteString("\nYou'll need to sign into your GoToSocial's consent page in order to generate the out-of-band token to continue with the application's login process.")
63  	builder.WriteString("\nYour browser may have opened the link to the consent page already. If not, please copy and paste the link below to your browser:")
64  	builder.WriteString("\n\n" + consentPageURL)
65  	builder.WriteString("\n\n" + "Once you have the code please copy and paste it below.")
66  	builder.WriteString("\n" + "Out-of-band token: ")
67  
68  	printer.PrintInfo(builder.String())
69  
70  	var code string
71  
72  	if _, err := fmt.Scanln(&code); err != nil {
73  		return fmt.Errorf("failed to read access code: %w", err)
74  	}
75  
76  	if err := client.Call("GTSClient.UpdateToken", code, &auth); err != nil {
77  		return fmt.Errorf("unable to update the client's access token: %w", err)
78  	}
79  
80  	var account model.Account
81  	if err := client.Call("GTSClient.VerifyCredentials", gtsclient.NoRPCArgs{}, &account); err != nil {
82  		return fmt.Errorf("unable to verify the credentials: %w", err)
83  	}
84  
85  	loginName, err := config.SaveCredentials(l.config.CredentialsFile, account.Username, auth)
86  	if err != nil {
87  		return fmt.Errorf("unable to save the authentication details: %w", err)
88  	}
89  
90  	printer.PrintSuccess(l.printSettings, "You have successfully logged in as "+loginName+".")
91  
92  	return nil
93  }