...
1 package emulatorsvc
2
3 import (
4 "bufio"
5 "errors"
6 "fmt"
7 "io/fs"
8 "os"
9 "path/filepath"
10
11 "golang.org/x/term"
12 "gopkg.in/yaml.v2"
13 )
14
15 const (
16 envFilePathDir = "RCLI_WORKSPACE_DIR"
17 defaultDir = "./"
18 authFileName = "rcli_auth.yaml"
19
20 DefaultProfileName = "default"
21
22 ProfileFlag = "profile"
23 UsernameFlag = "username"
24 PasswordFlag = "password"
25 Endpoint = "api-endpoint"
26 OrganizationFlag = "organization"
27 )
28
29 type AuthFile struct {
30 path string
31 DefaultProfile string `yaml:"defaultProfile"`
32 Profiles map[string]Profile `yaml:"profiles"`
33 }
34
35 func OpenAuthFile(dir string) (*AuthFile, error) {
36 path := filepath.Join(dir, authFileName)
37 auth := AuthFile{path: path}
38 auth.Profiles = make(map[string]Profile)
39
40 data, err := os.ReadFile(path)
41
42 if errors.Is(err, fs.ErrNotExist) {
43 return &auth, nil
44 }
45 if err != nil {
46 return nil, err
47 }
48 err = yaml.UnmarshalStrict(data, &auth)
49 if err != nil {
50 return nil, err
51 }
52 return &auth, nil
53 }
54
55 func (af AuthFile) Path() string {
56 return af.path
57 }
58
59 func (af *AuthFile) isInitialized() bool {
60 return af.DefaultProfile != "" && len(af.Profiles) > 0
61 }
62
63 func (af *AuthFile) UpdateAuthFile(profile Profile, name string) error {
64 if af.isInitialized() {
65 return nil
66 }
67
68
69 if af.DefaultProfile == "" {
70 if name != "" {
71 af.DefaultProfile = name
72 } else {
73 af.DefaultProfile = DefaultProfileName
74 }
75 }
76
77 if len(af.Profiles) == 0 {
78 af.Profiles[af.DefaultProfile] = profile
79 }
80 return af.writeFile()
81 }
82
83 func (af *AuthFile) writeFile() error {
84 var data []byte
85 data, err := yaml.Marshal(af)
86 if err != nil {
87 return err
88 }
89 return os.WriteFile(af.path, data, 0640)
90 }
91
92 func (af *AuthFile) LoadProfile(profile Profile, name string) (Profile, error) {
93
94 if !af.isInitialized() {
95 return profile, nil
96 }
97
98 if name == "" {
99 name = af.DefaultProfile
100 }
101
102 p, ok := af.Profiles[name]
103 if !ok {
104 return Profile{}, fmt.Errorf("profile does not exist in rcli auth file")
105 }
106
107 if profile.Username == "" {
108 profile.Username = p.Username
109 }
110 if profile.Organization == "" {
111 profile.Organization = p.Organization
112 }
113 if profile.API == "" {
114 profile.API = p.API
115 }
116 return profile, nil
117 }
118
119 type Config struct {
120 dir string
121 Profile Profile
122 }
123
124 func NewConfig(dir string, profile Profile) Config {
125 return Config{
126 dir: dir,
127 Profile: profile,
128 }
129 }
130
131 type Profile struct {
132 Username string `yaml:"username"`
133 Password string `yaml:"-"`
134 API string `yaml:"apiEndpoint"`
135 Organization string `yaml:"organization"`
136 SessionCookie string `yaml:"-"`
137 }
138
139 func (profile *Profile) RequestEmptyFields() error {
140 var err error
141 if profile.Username == "" {
142 fmt.Print("Please enter your username: ")
143 profile.Username, err = promptGeneric()
144 if err != nil {
145 return err
146 }
147 }
148 if profile.Password == "" {
149 fmt.Print("Please enter your password: ")
150 profile.Password, err = promptPassword()
151 if err != nil {
152 return err
153 }
154 }
155 if profile.API == "" {
156 fmt.Print("Please enter the Edge API URL: ")
157 profile.API, err = promptGeneric()
158 if err != nil {
159 return err
160 }
161 }
162 if profile.Organization == "" {
163 fmt.Print("Please enter your Edge organization: ")
164 profile.Organization, err = promptGeneric()
165 if err != nil {
166 return err
167 }
168 }
169 return nil
170 }
171
172 func promptGeneric() (string, error) {
173 var input string
174 scanner := bufio.NewScanner(os.Stdin)
175 for scanner.Scan() {
176 if err := scanner.Err(); err != nil {
177 return "", err
178 }
179 if input = scanner.Text(); input != "" {
180 break
181 }
182 fmt.Print("Please enter a valid value: ")
183 }
184 return input, nil
185 }
186
187 func promptPassword() (string, error) {
188 byteInput, err := term.ReadPassword(int(os.Stdin.Fd()))
189 if err != nil {
190 return "", err
191 }
192 fmt.Println()
193 for string(byteInput) == "" {
194 fmt.Print("Please enter a valid value: ")
195 byteInput, err = term.ReadPassword(int(os.Stdin.Fd()))
196 if err != nil {
197 return "", err
198 }
199 fmt.Println()
200 }
201 return string(byteInput), nil
202 }
203
View as plain text