forked from RiotGames/key-conjurer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
accounts.go
119 lines (99 loc) · 3.31 KB
/
accounts.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"github.com/riotgames/key-conjurer/internal/api"
"github.com/spf13/cobra"
"golang.org/x/oauth2"
)
var (
FlagNoRefresh = "no-refresh"
FlagServerAddress = "server-address"
ErrSessionExpired = errors.New("session expired")
)
func init() {
accountsCmd.Flags().Bool(FlagNoRefresh, false, "Indicate that the account list should not be refreshed when executing this command. This is useful if you're not able to reach the account server.")
accountsCmd.Flags().String(FlagServerAddress, ServerAddress, "The address of the account server. This does not usually need to be changed or specified.")
}
var accountsCmd = &cobra.Command{
Use: "accounts",
Short: "Prints and optionally refreshes the list of accounts you have access to.",
RunE: func(cmd *cobra.Command, args []string) error {
config := ConfigFromCommand(cmd)
stdOut := cmd.OutOrStdout()
noRefresh, _ := cmd.Flags().GetBool(FlagNoRefresh)
loud := !ShouldUseMachineOutput(cmd.Flags())
if noRefresh {
config.DumpAccounts(stdOut, loud)
if loud {
cmd.PrintErrf("--%s was specified - these results may be out of date, and you may not have access to accounts in this list.\n", FlagNoRefresh)
}
return nil
}
serverAddr, _ := cmd.Flags().GetString(FlagServerAddress)
serverAddrURI, err := url.Parse(serverAddr)
if err != nil {
cmd.PrintErrf("--%s had an invalid value: %s\n", FlagServerAddress, err)
return nil
}
if HasTokenExpired(config.Tokens) {
cmd.PrintErrln("Your session has expired. Please run login again.")
config.SaveOAuthToken(nil)
return nil
}
tok := oauth2.Token{
AccessToken: config.Tokens.AccessToken,
RefreshToken: config.Tokens.RefreshToken,
Expiry: config.Tokens.Expiry,
TokenType: config.Tokens.TokenType,
}
accounts, err := refreshAccounts(cmd.Context(), serverAddrURI, &tok)
if err != nil {
cmd.PrintErrf("Error refreshing accounts: %s\n", err)
cmd.PrintErrln("If you don't need to refresh your accounts, consider adding the --no-refresh flag")
return nil
}
config.UpdateAccounts(accounts)
config.DumpAccounts(stdOut, loud)
return nil
},
}
func refreshAccounts(ctx context.Context, serverAddr *url.URL, tok *oauth2.Token) ([]Account, error) {
uri := serverAddr.ResolveReference(&url.URL{Path: "/v2/applications"})
httpClient := NewHTTPClient()
req, _ := http.NewRequestWithContext(ctx, "POST", uri.String(), nil)
tok.SetAuthHeader(req)
resp, err := httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to issue request: %s", err)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("could not read body: %s", err)
}
var jsonError api.JSONError
if resp.StatusCode != http.StatusOK && resp.StatusCode != 0 {
if err := json.Unmarshal(body, &jsonError); err != nil {
return nil, errors.New(jsonError.Message)
}
return nil, fmt.Errorf("status code %d", resp.StatusCode)
}
var apps []api.Application
if err := json.Unmarshal(body, &apps); err != nil {
return nil, fmt.Errorf("failed to unmarshal applications: %w", err)
}
entries := make([]Account, len(apps))
for idx, app := range apps {
entries[idx] = Account{
ID: app.ID,
Name: app.Name,
Alias: generateDefaultAlias(app.Name),
}
}
return entries, nil
}