Skip to content

Commit f079eca

Browse files
[Storage Explorer] _token_refresh_source type change (#2710)
* [Storage Explorer] _token_refresh_source type change * [Storage Explorer] _token_refresh_source type change * incorporated review comments * incorporated review comments
1 parent e8aa4b6 commit f079eca

File tree

2 files changed

+215
-1
lines changed

2 files changed

+215
-1
lines changed

common/environment.go

+30-1
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@
2121
package common
2222

2323
import (
24-
"github.com/JeffreyRichter/enum/enum"
24+
"encoding/json"
25+
"fmt"
2526
"reflect"
2627
"runtime"
2728
"strings"
29+
30+
"github.com/JeffreyRichter/enum/enum"
2831
)
2932

3033
type EnvironmentVariable struct {
@@ -115,6 +118,32 @@ func (d *AutoLoginType) Parse(s string) error {
115118
return err
116119
}
117120

121+
// MarshalJSON customizes the JSON encoding for AutoLoginType
122+
func (d AutoLoginType) MarshalJSON() ([]byte, error) {
123+
return json.Marshal(d.String())
124+
}
125+
126+
// UnmarshalJSON customizes the JSON decoding for AutoLoginType
127+
func (d *AutoLoginType) UnmarshalJSON(data []byte) error {
128+
var v interface{}
129+
if err := json.Unmarshal(data, &v); err != nil {
130+
return err
131+
}
132+
if strValue, ok := v.(string); ok {
133+
return d.Parse(strValue)
134+
}
135+
// Handle numeric values
136+
if numValue, ok := v.(float64); ok {
137+
if numValue < 0 || numValue > 255 {
138+
return fmt.Errorf("value out of range for _token_source_refresh: %v", numValue)
139+
}
140+
*d = AutoLoginType(uint8(numValue))
141+
return nil
142+
}
143+
144+
return fmt.Errorf("unsupported type for AutoLoginType: %T", v)
145+
}
146+
118147
func ValidAutoLoginTypes() []string {
119148
return []string{
120149
EAutoLoginType.Device().String() + " (Device code workflow)",

common/oauthTokenManager_test.go

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
// Copyright © 2017 Microsoft <wastore@microsoft.com>
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy
4+
// of this software and associated documentation files (the "Software"), to deal
5+
// in the Software without restriction, including without limitation the rights
6+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
// copies of the Software, and to permit persons to whom the Software is
8+
// furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
// THE SOFTWARE.
20+
21+
package common
22+
23+
import (
24+
"context"
25+
"fmt"
26+
"os"
27+
"reflect"
28+
"strconv"
29+
"testing"
30+
)
31+
32+
const tokenInfoJson = `{
33+
"access_token": "dummy_access_token",
34+
"refresh_token": "dummy_refresh_token",
35+
"expires_in": 0,
36+
"expires_on": 0,
37+
"not_before": 0,
38+
"resource": "dummy_resource",
39+
"token_type": "dummy_token_type",
40+
"_tenant": "dummy_tenant",
41+
"_ad_endpoint": "dummy_ad_endpoint",
42+
"_token_refresh_source": %v,
43+
"_application_id": "dummy_application_id",
44+
"IdentityInfo": {
45+
"_identity_client_id": "dummy_identity_client_id",
46+
"_identity_object_id": "dummy_identity_object_id",
47+
"_identity_msi_res_id": "dummy_identity_msi_res_id"
48+
},
49+
"SPNInfo": {
50+
"_spn_secret": "dummy_spn_secret",
51+
"_spn_cert_path": "dummy_spn_cert_path"
52+
}
53+
}`
54+
55+
var oauthTokenInfo = OAuthTokenInfo{
56+
Tenant: "dummy_tenant",
57+
ActiveDirectoryEndpoint: "dummy_ad_endpoint",
58+
LoginType: 255,
59+
ApplicationID: "dummy_application_id",
60+
IdentityInfo: IdentityInfo{
61+
ClientID: "dummy_identity_client_id",
62+
ObjectID: "dummy_identity_object_id",
63+
MSIResID: "dummy_identity_msi_res_id",
64+
},
65+
SPNInfo: SPNInfo{
66+
Secret: "dummy_spn_secret",
67+
CertPath: "dummy_spn_cert_path",
68+
},
69+
}
70+
71+
func formatTokenInfo(value interface{}) string {
72+
var formattedValue string
73+
switch v := value.(type) {
74+
case string:
75+
formattedValue = fmt.Sprintf("\"%s\"", v)
76+
case int:
77+
formattedValue = strconv.Itoa(v)
78+
default:
79+
formattedValue = fmt.Sprintf("%v", v)
80+
}
81+
return fmt.Sprintf(tokenInfoJson, formattedValue)
82+
}
83+
84+
func TestUserOAuthTokenManager_GetTokenInfo(t *testing.T) {
85+
type args struct {
86+
ctx context.Context
87+
}
88+
tests := []struct {
89+
name string
90+
uotm *UserOAuthTokenManager
91+
args args
92+
setup func(t *testing.T)
93+
want *OAuthTokenInfo
94+
wantErr bool
95+
}{
96+
{
97+
name: "This UT tests if AutoLoginType filled is parsed properly from string to uint8 data type",
98+
uotm: &UserOAuthTokenManager{},
99+
args: args{
100+
ctx: context.Background(),
101+
},
102+
setup: func(t *testing.T) {
103+
tokenInfo := formatTokenInfo("TokenStore")
104+
fmt.Println(tokenInfo)
105+
106+
// Set the environment variable AZCOPY_OAUTH_TOKEN_INFO
107+
err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfo)
108+
if err != nil {
109+
t.Fatalf("Failed to set environment variable: %v", err)
110+
}
111+
},
112+
want: &oauthTokenInfo,
113+
wantErr: false,
114+
},
115+
{
116+
name: "This UT tests if AutoLoginType filled is assigned properly to uint8 data type",
117+
uotm: &UserOAuthTokenManager{},
118+
args: args{
119+
ctx: context.Background(),
120+
},
121+
setup: func(t *testing.T) {
122+
tokenInfo := formatTokenInfo(255)
123+
fmt.Println(tokenInfo)
124+
125+
// Set the environment variable AZCOPY_OAUTH_TOKEN_INFO
126+
err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfo)
127+
if err != nil {
128+
t.Fatalf("Failed to set environment variable: %v", err)
129+
}
130+
},
131+
want: &oauthTokenInfo,
132+
wantErr: false,
133+
},
134+
{
135+
name: "This UT tests if _token_refresh_source fails to parse due to invalid string type",
136+
uotm: &UserOAuthTokenManager{},
137+
args: args{
138+
ctx: context.Background(),
139+
},
140+
setup: func(t *testing.T) {
141+
tokenInfo := formatTokenInfo("2gt5")
142+
143+
// Set the environment variable AZCOPY_OAUTH_TOKEN_INFO
144+
err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfo)
145+
if err != nil {
146+
t.Fatalf("Failed to set environment variable: %v", err)
147+
}
148+
},
149+
want: nil,
150+
wantErr: true,
151+
},
152+
{
153+
name: "This UT tests if _token_refresh_source fails to parse due to value out of uint8 range",
154+
uotm: &UserOAuthTokenManager{},
155+
args: args{
156+
ctx: context.Background(),
157+
},
158+
setup: func(t *testing.T) {
159+
tokenInfo := formatTokenInfo(847)
160+
161+
// Set the environment variable AZCOPY_OAUTH_TOKEN_INFO
162+
err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfo)
163+
if err != nil {
164+
t.Fatalf("Failed to set environment variable: %v", err)
165+
}
166+
},
167+
want: nil,
168+
wantErr: true,
169+
},
170+
}
171+
for _, tt := range tests {
172+
t.Run(tt.name, func(t *testing.T) {
173+
174+
tt.setup(t)
175+
got, err := tt.uotm.GetTokenInfo(tt.args.ctx)
176+
if (err != nil) != tt.wantErr {
177+
t.Errorf("UserOAuthTokenManager.GetTokenInfo() error = %v, wantErr %v", err, tt.wantErr)
178+
return
179+
}
180+
if got != nil && reflect.DeepEqual(got, tt.want) {
181+
t.Errorf("UserOAuthTokenManager.GetTokenInfo() = %v, want %v", got, tt.want)
182+
}
183+
})
184+
}
185+
}

0 commit comments

Comments
 (0)