GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

ider.getCredentials   F
last analyzed

Complexity

Conditions 16

Size

Total Lines 78
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 54
nop 0
dl 0
loc 78
rs 2.4
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like providers.*CloudSSOCredentialsProvider.getCredentials often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package providers
2
3
import (
4
	"encoding/json"
5
	"errors"
6
	"fmt"
7
	"net/http"
8
	"net/url"
9
	"time"
10
11
	httputil "github.com/aliyun/credentials-go/credentials/internal/http"
12
)
13
14
type CloudSSOCredentialsProvider struct {
15
	signInUrl         string
16
	accountId         string
17
	accessConfig      string
18
	accessToken       string
19
	accessTokenExpire int64
20
21
	lastUpdateTimestamp int64
22
	expirationTimestamp int64
23
	sessionCredentials  *sessionCredentials
24
	// for http options
25
	httpOptions *HttpOptions
26
}
27
28
type CloudSSOCredentialsProviderBuilder struct {
29
	provider *CloudSSOCredentialsProvider
30
}
31
32
type cloudCredentialOptions struct {
33
	AccountId             string `json:"AccountId"`
34
	AccessConfigurationId string `json:"AccessConfigurationId"`
35
}
36
37
type cloudCredentials struct {
38
	AccessKeyId     string `json:"AccessKeyId"`
39
	AccessKeySecret string `json:"AccessKeySecret"`
40
	SecurityToken   string `json:"SecurityToken"`
41
	Expiration      string `json:"Expiration"`
42
}
43
44
type cloudCredentialResponse struct {
45
	CloudCredential *cloudCredentials `json:"CloudCredential"`
46
	RequestId       string            `json:"RequestId"`
47
}
48
49
func NewCloudSSOCredentialsProviderBuilder() *CloudSSOCredentialsProviderBuilder {
50
	return &CloudSSOCredentialsProviderBuilder{
51
		provider: &CloudSSOCredentialsProvider{},
52
	}
53
}
54
55
func (b *CloudSSOCredentialsProviderBuilder) WithSignInUrl(signInUrl string) *CloudSSOCredentialsProviderBuilder {
56
	b.provider.signInUrl = signInUrl
57
	return b
58
}
59
60
func (b *CloudSSOCredentialsProviderBuilder) WithAccountId(accountId string) *CloudSSOCredentialsProviderBuilder {
61
	b.provider.accountId = accountId
62
	return b
63
}
64
65
func (b *CloudSSOCredentialsProviderBuilder) WithAccessConfig(accessConfig string) *CloudSSOCredentialsProviderBuilder {
66
	b.provider.accessConfig = accessConfig
67
	return b
68
}
69
70
func (b *CloudSSOCredentialsProviderBuilder) WithAccessToken(accessToken string) *CloudSSOCredentialsProviderBuilder {
71
	b.provider.accessToken = accessToken
72
	return b
73
}
74
75
func (b *CloudSSOCredentialsProviderBuilder) WithAccessTokenExpire(accessTokenExpire int64) *CloudSSOCredentialsProviderBuilder {
76
	b.provider.accessTokenExpire = accessTokenExpire
77
	return b
78
}
79
80
func (b *CloudSSOCredentialsProviderBuilder) WithHttpOptions(httpOptions *HttpOptions) *CloudSSOCredentialsProviderBuilder {
81
	b.provider.httpOptions = httpOptions
82
	return b
83
}
84
85
func (b *CloudSSOCredentialsProviderBuilder) Build() (provider *CloudSSOCredentialsProvider, err error) {
86
	if b.provider.accessToken == "" || b.provider.accessTokenExpire == 0 || b.provider.accessTokenExpire-time.Now().Unix() <= 0 {
87
		err = errors.New("CloudSSO access token is empty or expired, please re-login with cli")
88
		return
89
	}
90
91
	if b.provider.signInUrl == "" || b.provider.accountId == "" || b.provider.accessConfig == "" {
92
		err = errors.New("CloudSSO sign in url or account id or access config is empty")
93
		return
94
	}
95
96
	provider = b.provider
97
	return
98
}
99
100
func (provider *CloudSSOCredentialsProvider) getCredentials() (session *sessionCredentials, err error) {
101
	url, err := url.Parse(provider.signInUrl)
102
	if err != nil {
103
		return nil, err
104
	}
105
106
	req := &httputil.Request{
107
		Method:   "POST",
108
		Protocol: url.Scheme,
109
		Host:     url.Host,
110
		Path:     "/cloud-credentials",
111
		Headers:  map[string]string{},
112
	}
113
114
	connectTimeout := 5 * time.Second
115
	readTimeout := 10 * time.Second
116
117
	if provider.httpOptions != nil && provider.httpOptions.ConnectTimeout > 0 {
118
		connectTimeout = time.Duration(provider.httpOptions.ConnectTimeout) * time.Millisecond
119
	}
120
	if provider.httpOptions != nil && provider.httpOptions.ReadTimeout > 0 {
121
		readTimeout = time.Duration(provider.httpOptions.ReadTimeout) * time.Millisecond
122
	}
123
	if provider.httpOptions != nil && provider.httpOptions.Proxy != "" {
124
		req.Proxy = provider.httpOptions.Proxy
125
	}
126
	req.ConnectTimeout = connectTimeout
127
	req.ReadTimeout = readTimeout
128
129
	body := cloudCredentialOptions{
130
		AccountId:             provider.accountId,
131
		AccessConfigurationId: provider.accessConfig,
132
	}
133
134
	bodyBytes, err := json.Marshal(body)
135
	if err != nil {
136
		return nil, fmt.Errorf("failed to marshal options: %w", err)
137
	}
138
139
	req.Body = bodyBytes
140
141
	// set headers
142
	req.Headers["Accept"] = "application/json"
143
	req.Headers["Content-Type"] = "application/json"
144
	req.Headers["Authorization"] = fmt.Sprintf("Bearer %s", provider.accessToken)
145
	res, err := httpDo(req)
146
	if err != nil {
147
		return
148
	}
149
150
	if res.StatusCode != http.StatusOK {
151
		message := "get session token from sso failed: "
152
		err = errors.New(message + string(res.Body))
153
		return
154
	}
155
	var data cloudCredentialResponse
156
	err = json.Unmarshal(res.Body, &data)
157
	if err != nil {
158
		err = fmt.Errorf("get session token from sso failed, json.Unmarshal fail: %s", err.Error())
159
		return
160
	}
161
	if data.CloudCredential == nil {
162
		err = fmt.Errorf("get session token from sso failed, fail to get credentials")
163
		return
164
	}
165
166
	if data.CloudCredential.AccessKeyId == "" || data.CloudCredential.AccessKeySecret == "" || data.CloudCredential.SecurityToken == "" {
167
		err = fmt.Errorf("refresh session token err, fail to get credentials")
168
		return
169
	}
170
171
	session = &sessionCredentials{
172
		AccessKeyId:     data.CloudCredential.AccessKeyId,
173
		AccessKeySecret: data.CloudCredential.AccessKeySecret,
174
		SecurityToken:   data.CloudCredential.SecurityToken,
175
		Expiration:      data.CloudCredential.Expiration,
176
	}
177
	return
178
}
179
180
func (provider *CloudSSOCredentialsProvider) needUpdateCredential() (result bool) {
181
	if provider.expirationTimestamp == 0 {
182
		return true
183
	}
184
185
	return provider.expirationTimestamp-time.Now().Unix() <= 180
186
}
187
188
func (provider *CloudSSOCredentialsProvider) GetCredentials() (cc *Credentials, err error) {
189
	if provider.sessionCredentials == nil || provider.needUpdateCredential() {
190
		sessionCredentials, err1 := provider.getCredentials()
191
		if err1 != nil {
192
			return nil, err1
193
		}
194
195
		provider.sessionCredentials = sessionCredentials
196
		expirationTime, err2 := time.Parse("2006-01-02T15:04:05Z", sessionCredentials.Expiration)
197
		if err2 != nil {
198
			return nil, err2
199
		}
200
201
		provider.lastUpdateTimestamp = time.Now().Unix()
202
		provider.expirationTimestamp = expirationTime.Unix()
203
	}
204
205
	cc = &Credentials{
206
		AccessKeyId:     provider.sessionCredentials.AccessKeyId,
207
		AccessKeySecret: provider.sessionCredentials.AccessKeySecret,
208
		SecurityToken:   provider.sessionCredentials.SecurityToken,
209
		ProviderName:    provider.GetProviderName(),
210
	}
211
	return
212
}
213
214
func (provider *CloudSSOCredentialsProvider) GetProviderName() string {
215
	return "cloud_sso"
216
}
217